插入排序的思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子数组中的适当位置,直到全部记录插入完成为止。
一、直接插入排序
#include <iostream> using namespace::std; //打印 void print_array(int a[], int n) { for(int i = 0; i < n; i++) cout << a[i] << "," ; cout << endl; } //排序 void insert_sort(int a[], int n) { int tmp = 0; int j = 0; for(int i = 1; i < n; i++) { //暂存下标为i的数,下标从1开始,因为a[0]已经排好序 tmp = a[i]; for(j = i - 1; j >= 0 && tmp < a[j]; j--) { //发现a[i]比前面的a[j]小,就把a[j]往后挪,再将tmp=a[i]放在合适的位置 a[j+1] = a[j]; } //放入tmp=a[i] a[j+1] = tmp; print_array(a, n); } } int main() { int a[] = {7,3,5,8,9,1,2,4,6}; cout << "before sort:" << endl; print_array(a, 9); insert_sort(a, 9); cout << "after sort :" << endl; print_array(a, 9); return 0; }
输出:
说明:
直接插入排序的做法是:每次从无序表中取出第一个元素,插入到有序表的合适位置。第一次比较前两个数,把较大的放在后面;第二次取第三个数与前两个数从后往前扫描,然后插入到合适的位置;依次下去进行了(n-1)次扫描完成了整个过程。
直接插入排序属于稳定排序,最坏时间复杂性为O(n^2),空间复杂度O(1)。
二、希尔(Shell)排序
#include <iostream> using namespace std; void print_array(int a[], int n) { for(int i = 0; i < n; i++) cout << a[i] << "," ; cout << endl; } void shell_sort(int a[], int n) { int tmp = 0, j = 0; //h是每次循环的增量,依次减半 for(int h = n / 2; h > 0; h /= 2) { for(int i = h; i < n; i++) { tmp = a[i]; for(j = i - h; (j>=0 && tmp < a[j]); j-=h) { a[j+h] = a[j]; } cout << "before: " << tmp << " "; print_array(a, 9); a[j+h] = tmp; cout << "after : " << " "; print_array(a, 9); } } } int main() { int a[] = {7,3,5,8,9,1,2,4,6}; //cout << "before sort:" << endl; print_array(a, 9); shell_sort(a, 9); //cout << "after sort :" << endl; print_array(a, 9); return 0; }
输出:
说明:
希尔排序是插入排序的一种。是针对直接插入排序的改进。又称为缩小增量排序,属于不稳定排序方法。
在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,且对插入的下一个数没有帮助。如果比较相隔较远(增量大)的数,使得数移动能跨过多个元素,就可以避免多次交换了。
希尔排序算法是将数组按照增量d分成若干组,组之间对应元素进行比较,然后交换;然后将增量缩小,再次进行分组,组之间对应元素进行比较,直到增量变为1。因此希尔排序实际上是一种分组插入方法。