概述
插入排序算法(稳定)
直接插入,平均情况O(n2),最好情况O(n),最坏情况O(n2),辅助空间O(1),稳定。
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
解题思路:
- 设数组为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。排序完成
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 2 | 3 | 4 | 8 | 9 | 6 | 7 | 10 | 0 |
分析:
如上图所示,若想将元素6(位序i=6)插入到前边已经排好顺序的数组中,需要先找到元素6所归属的位置i,因为元素6的下标为6,即i=6,所以应该从下标为5(即i-1)的位置开始向前寻找,找到比元素6小的位置j,( 注意:找到元素6位置i之后的位置是无用的,因为j本来就在i之前的第一个位置上),并将该位置之后(j+1)的元素,6之前(即i-1)的元素的位置依次向后移动,并将元素6插入到j之后的位置,即(j+1)的位置;
根据上述分析,很容易写出代码(由小到大排序):
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Show(int *arr, int n)
{
for (int i = 0; i < n; i++)
printf("%-5d", arr[i]);
printf("n");
}
void InsertSort(int *arr, int n)
{
int i, j, k;
for (i = 1; i < n; i++)
{
//为a[i]找到要插入的位置
for (j = i - 1; j >= 0; j--)
if (arr[i] > arr[j])
break;
//如果找到了一个合适的位置,注意,找到a[i]之后的位置是没有意义的
if (j != i - 1)
{
//将比a[i]大的所有元素后移
int temp = arr[i];
for (k = i - 1; k > j; k--)
arr[k + 1] = arr[k];
arr[j+1] = temp;
}
}
}
void main()
{
int arr[100] = { 0 };
time_t time1;
srand((unsigned int)time(&time1));
for (int i = 0; i < 100; i++)
arr[i] = rand() % 100;
printf("排序之前的数据:n");
Show(arr, 100);
printf("排序之后的数据:n");
InsertSort(arr, 100);
Show(arr, 100);
system("pause");
}
运行结果:
排序之前的数据:
29 64 22 30 56 16 21 34 57 34 83 99 65 91 4 7
15 78 45 24 93 49 74 91 59 0 19 86 94 84 14 6
15 74 54 39 9 25 54 92 4 66 90 17 27 54 25 22
51 15 14 41 4 99 64 4 1 4 16 57 55 64 98 13
91 27 30 34 93 75 73 29 23 94 54 88 73 27 58 48
52 26 16 9 67 93 9 16 67 7 70 77 61 39 90 7
25 10 79 85
排序之后的数据:
0 1 4 4 4 4 4 6 7 7 7 9 9 9 10 13
14 14 15 15 15 16 16 16 16 17 19 21 22 22 23 24
25 25 25 26 27 27 27 29 29 30 30 34 34 34 39 39
41 45 48 49 51 52 54 54 54 54 55 56 57 57 58 59
61 64 64 64 65 66 67 67 70 73 73 74 74 75 77 78
79 83 84 85 86 88 90 90 91 91 91 92 93 93 93 94
94 98 99 99
请按任意键继续. . .
优化一
这样的代码太长了,不够清晰。现在进行一下改写,将搜索和数据后移这二个步骤合并。即每次a[i]先和前面一个数据a[i-1]比较,如果a[i] > a[i-1]说明a[0…i]也是有序的,无须调整。否则就令j=i-1,temp=a[i]。然后一边将数据a[j]向后移动一边向前搜索,当有数据a[j]<a[i]时停止并将temp放到a[j + 1]处。
代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Show(int *arr, int n)
{
for (int i = 0; i < n; i++)
printf("%-5d", arr[i]);
printf("n");
}
void InsertSort(int *arr, int n)
{
int i, j;
for (i = 1; i < n; i++)
{
if (arr[i] < arr[i - 1])
{
int temp = arr[i];
for (j = i - 1; j >= 0 && arr[j] > temp; j--)
arr[j + 1] = arr[j];
arr[j + 1] = temp;
}
}
}
void main()
{
int arr[100] = { 0 };
time_t time1;
srand((unsigned int)time(&time1));
for (int i = 0; i < 100; i++)
arr[i] = rand() % 100;
printf("排序之前的数据:n");
Show(arr, 100);
printf("排序之后的数据:n");
InsertSort(arr, 100);
Show(arr, 100);
system("pause");
}
运行结果:
排序之前的数据:
0 44 4 22 28 54 8 2 72 96 70 43 28 43 49 40
99 65 62 28 77 95 77 75 20 16 74 76 57 71 60 19
10 72 26 44 87 80 60 77 65 65 1 65 44 40 94 46
36 18 45 92 7 81 27 46 70 16 10 52 62 56 91 14
92 12 36 84 99 39 45 90 41 1 16 2 57 31 10 4
19 67 80 41 64 44 17 91 43 93 76 7 84 32 82 64
88 4 17 76
排序之后的数据:
0 1 1 2 2 4 4 4 7 7 8 10 10 10 12 14
16 16 16 17 17 18 19 19 20 22 26 27 28 28 28 31
32 36 36 39 40 40 41 41 43 43 43 44 44 44 44 45
45 46 46 49 52 54 56 57 57 60 60 62 62 64 64 65
65 65 65 67 70 70 71 72 72 74 75 76 76 76 77 77
77 80 80 81 82 84 84 87 88 90 91 91 92 92 93 94
95 96 99 99
请按任意键继续. . .
优化二
再对将a[j]插入到前面a[0…j-1]的有序区间所用的方法进行改写,用数据交换代替数据后移。如果a[j]前一个数据a[j-1] > a[j],就交换a[j]和a[j-1],再j--直到a[j-1] <= a[j]。这样也可以实现将一个新数据新并入到有序区间。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Show(int *arr, int n)
{
for (int i = 0; i < n; i++)
printf("%-5d", arr[i]);
printf("n");
}
void Swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void InsertSort(int *arr, int n)
{
int i, j;
for (i = 1; i < n; i++)
{
for (j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--)
Swap(&arr[j], &arr[j + 1]);
}
}
void main()
{
int arr[100] = { 0 };
time_t time1;
srand((unsigned int)time(&time1));
for (int i = 0; i < 100; i++)
arr[i] = rand() % 100;
printf("排序之前的数据:n");
Show(arr, 100);
printf("排序之后的数据:n");
InsertSort(arr, 100);
Show(arr, 100);
system("pause");
}
运算结果:
排序之前的数据:
33 95 26 23 40 39 69 57 31 54 21 98 82 2 78 34
84 69 18 51 97 16 18 98 43 15 48 50 3 55 5 27
42 0 38 67 85 72 8 9 84 99 44 87 9 97 4 2
9 81 39 63 11 60 23 37 50 97 77 52 31 13 61 35
86 30 99 25 73 84 56 68 13 88 57 0 90 84 17 71
73 66 81 73 64 85 1 18 4 2 61 13 26 27 97 67
0 97 0 13
排序之后的数据:
0 0 0 0 1 2 2 2 3 4 4 5 8 9 9 9
11 13 13 13 13 15 16 17 18 18 18 21 23 23 25 26
26 27 27 30 31 31 33 34 35 37 38 39 39 40 42 43
44 48 50 50 51 52 54 55 56 57 57 60 61 61 63 64
66 67 67 68 69 69 71 72 73 73 73 77 78 81 81 82
84 84 84 84 85 85 86 87 88 90 95 97 97 97 97 97
98 98 99 99
注意:最后一种算法的思想和冒泡排序算法的思想差不多!
引自<http://blog.csdn.net/morewindows/article/details/6665714>
最后
以上就是故意项链为你收集整理的经典排序算法----直接插入排序算法及其改进(稳定)插入排序算法(稳定)的全部内容,希望文章能够帮你解决经典排序算法----直接插入排序算法及其改进(稳定)插入排序算法(稳定)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复