排序算法(五)插入排序
从一个乱序的数组中依次取值,插入到一个已经排好序的数组中。 这看起来好像要两个数组才能完成,但如果只想在同一个数组内排序,也是可以的。此时需要想象出两个区域:前方有序区和后方乱序区。
设数组为a[0...n-1]。
- 初始时,a[0]自成1个有序区,无序区为a[1...n-1]。令i=1
- 将a[i]并入当前的有序区a[0...i-1]中形成a[0...i]的有序区间。
- i++并重复第二步直到i==n-1,排序完成。
下面给出严格按照定义书写的代码(由小到大排序):
1 void insertSort1(int data[], int len) 2 { 3 int i, j, k; 4 for (i = 1; i < len; i++) 5 { 6 //为data[i]在前面的data[0...i-1]有序区间中找一个合适的位置 7 for (j = i - 1; j >= 0;j--) 8 if (data[j] < data[i])//找到一个位置时,即停止 9 break; 10 11 //如找到一个合适的位置 12 if (j != i - 1) 13 { 14 //将比data[i]大的数据向后移 15 int temp = data[i]; 16 for (k = i - 1; k>j; k--) 17 data[k + 1] = data[k]; 18 19 //执行完上面的for循环后,k=j,而因为temp>data[j],所以将temp放在序号j的后面一个位置中 20 data[k + 1] = temp; 21 } 22 } 23 }
这样的代码太长了,不够清晰。现在进行一下改写,将搜索和数据后移这两个步骤合并。即每次data[i]先和前面一个数据data[i-1](因为无序区间中,i从1开始)比较,如果data[i]>data[i-1],说明data[0...i]也是有序的,无须调整。否则,就令j=i-1,temp=data[i].然后一边将数据data[j]向后移动一边向前搜索,当有数据data[j]<data[i]时停止,并将temp放到data[j+1]处。
1 /* 2 @将搜索和数据后移这两个步骤合并 3 */ 4 void insertSort2(int data[], int len) 5 { 6 int i, j; 7 for (i = 1; i < len;i++) 8 if (data[i] < data[i - 1])//当无序区间中的元素比有序区间的小时,说明需要调整 9 { 10 int temp = data[i];//临时存放要调整的元素 11 for (j = i - 1; j >= 0 && data[j]>temp; j--)//当有数据data[j]<data[i]时(即data[j]<temp)停止并将temp放到data[j+1] 12 data[j + 1] = data[j]; 13 data[j + 1] = temp; 14 } 15 }
也可对将data[j]插入到前面data[0...j-1]的有序区间所用的方法进行改写,用数据交换代替数据后移。如果data[j]前一个数据data[j-1]>data[j],就交换data[j]和data[j-1],再j--知道data[j-1]<=data[j]。这样就可以实现将一个新数据新并入到有序区间。
1 /* 2 @用数据交换代替数据后移 3 */ 4 void insertSort3(int data[], int len) 5 { 6 int i, j; 7 for (i = 1; i < len;i++) 8 for (j = i - 1; j >= 0 && data[j]>data[j + 1]; j--) 9 swap(data[j], data[j + 1]); 10 }
完整代码
1 /* 2 @theme:简单插入排序 3 @author:CodingMengmeng 4 @date:2016-11-10 12:16:32 5 @email:sprint_meng0116@163.com 6 */ 7 #include <iostream> 8 using namespace std; 9 /* 10 @严格按照定义书写的代码 11 */ 12 void insertSort1(int data[], int len) 13 { 14 int i, j, k; 15 for (i = 1; i < len; i++) 16 { 17 //为data[i]在前面的data[0...i-1]有序区间中找一个合适的位置 18 for (j = i - 1; j >= 0;j--) 19 if (data[j] < data[i])//找到一个位置时,即停止 20 break; 21 22 //如找到一个合适的位置 23 if (j != i - 1) 24 { 25 //将比data[i]大的数据向后移 26 int temp = data[i]; 27 for (k = i - 1; k>j; k--) 28 data[k + 1] = data[k]; 29 30 //执行完上面的for循环后,k=j,而因为temp>data[j],所以将temp放在序号j的后面一个位置中 31 data[k + 1] = temp; 32 } 33 } 34 } 35 36 /* 37 @将搜索和数据后移这两个步骤合并 38 */ 39 void insertSort2(int data[], int len) 40 { 41 int i, j; 42 for (i = 1; i < len;i++) 43 if (data[i] < data[i - 1])//当无序区间中的元素比有序区间的小时,说明需要调整 44 { 45 int temp = data[i];//临时存放要调整的元素 46 for (j = i - 1; j >= 0 && data[j]>temp; j--)//当有数据data[j]<data[i]时(即data[j]<temp)停止并将temp放到data[j+1] 47 data[j + 1] = data[j]; 48 data[j + 1] = temp; 49 } 50 } 51 52 /* 53 @用数据交换代替数据后移 54 */ 55 void insertSort3(int data[], int len) 56 { 57 int i, j; 58 for (i = 1; i < len;i++) 59 for (j = i - 1; j >= 0 && data[j]>data[j + 1]; j--) 60 swap(data[j], data[j + 1]); 61 } 62 int main(void) 63 { 64 int len;//要排序数组的长度 65 cout << "要排序数组的长度为:" << endl; 66 cin >> len; 67 int* data = (int*)malloc((len)*(sizeof(int)));//动态分配大小为len的int型数组 68 memset(data, 0, (len)*sizeof(int));//初始化数组的值为0,否则会出错 69 70 //读入数据 71 cout << "请输入" << len << "个数据:" << endl; 72 for (int i = 0; i < len; i++) 73 cin >> data[i]; 74 insertSort3(data, len); 75 //输出排序后的结果 76 cout << "插入排序后的结果:" << endl; 77 for (int i = 0; i < len; i++) 78 cout << data[i] << " "; 79 80 return 0; 81 }
运行结果:
それでも私の大好きな人