排序算法(五)插入排序

 

 

  

  从一个乱序的数组中依次取值,插入到一个已经排好序的数组中。 这看起来好像要两个数组才能完成,但如果只想在同一个数组内排序,也是可以的。此时需要想象出两个区域:前方有序区和后方乱序区。

  设数组为a[0...n-1]。

  1. 初始时,a[0]自成1个有序区,无序区为a[1...n-1]。令i=1
  2. 将a[i]并入当前的有序区a[0...i-1]中形成a[0...i]的有序区间。
  3. 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 }

 

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值