算法例题
用随机函数生成16个2位正整数(10~99),利用直接插入排序法将其排序。
算法思路
书面概括
- 将待排序的元素存放在数组r[1...n]中,r[1]是一个有序序列;
- 循环n-1次,每次使用顺序查找法,查找ri在已排好序的序列r[1...r-1]中的插入位置,然后将r[i]插入表长为i-1的有序序列r[1..i-1],直到将r[n]插入表长为n-1的有序序列r[1...n-1],最后得到一个表长为n的有序序列。
个人概括
1.引入一个无序序列
2.引入时就确定第一个为有序序列
3.将无序序列中第一个待排序元素加入监视哨
4.将无序序列中第一个待排序元素依次与有序序列中从大到小的元素比较
5.若待排序元素大于或等于有序序列中最大的元素,则直接插入到有序序列中的最后位置
6.若待排序元素小于有序序列中最大的元素,则逆序与有序序列的元素比较(省略了中间几步)
7.若待排序元素
- 小于有序序列中某个元素
- 小于有序序列中最小元素,这种情况也没有关系,因为我们有监视哨的存在
则要将有序序列中大于待排序元素的所有元素往后移,(就是给待排序元素腾位置),再将监视哨中保存的待排序元素插入有序序列适合的位置。
8.结果(省略n步)
考虑情况
排序过程会有三种情况
- 待排序元素大于有序序列中最大的元素;
- 待排序元素小于有序序列中的元素,但不小于有序序列中最小的元素;
- 待排序元素小于有序序列中最小的元素,但是因为监视哨的存在,2和3的情况归为一类。
算法效率
- 最好情况:待排序序列为顺序序列
- 比较次数KCN:n-1;
- 移动次数RMN:0;
- 最坏情况:待排序序列为逆序序列
- 比较次数KCN:2 + 3 + ... + n ≈ n²/2;
- 移动次数RMN:(2 + 1) + (3 + 1) + ... + (n + 1) ≈ n²/2;
所以时间复杂度为O(n²);
下面的代码是我按照自己的思路进行编写的,算法效率没有达到应有的程度。
空间复杂度为O(1),监视哨。
算法特点
- 稳定排序;
- 链式存储结构也适合;
- 更适合于初始记录基本有序(正序)的情况,当序列完全无序,尤其是逆序,且元素过多,时间复杂度会大大提高。
算法代码
#include<iostream> #include<ctime> using namespace std; void InsertSort(int* array, int n) { int recordMove = 0; int recordCompare = 0; for (int i = 1; i <= n; i++) { //记录有序序列中大于待排序元素的元素个数 int record = 0; //监视哨 array[0] = array[i]; //将待排序元素与有序序列中的元素从大到小进行比较 while (array[i] < array[i - record - 1]) { record++; recordCompare++; } //移动有序序列,给待排序元素腾空间 for (int k = 1; k <= record; k++) { array[i - k + 1] = array[i - k]; recordMove++; } //将待排序元素插入有序序列中 array[i - record] = array[0]; recordMove++; cout << "第" << i << "趟排序:" << endl; for (int j = 1; j <= 16; j++) { if( j == 1) cout << " [ "; cout << array[j] << " "; if (j == i) cout << " ] "; } cout << endl << endl; } cout << "比较次数:" << recordCompare << endl; cout << "移动次数:" << recordMove << endl << endl; } int main() { //生成随机16个正整数 int positiveInteger[17]; time_t t; srand((unsigned)time(&t)); cout << "生成16个2位正整数:" << endl; for (int i = 1; i <= 16; i++) { positiveInteger[i] = (rand() % (100 - 10)) + 10; cout << positiveInteger[i] << " "; } cout << endl << endl; //插入排序 InsertSort(positiveInteger, 16); //打印排序后数组 cout << "排序后数组:" << endl; for (int i = 1; i <= 16; i++) { cout << positiveInteger[i] << " "; } cout << endl << endl; system("pause"); return 0; }