voidshellSort(int a[], int n)//a -- 待排序的数组, n -- 数组的长度 { int i,j,gap; // gap为步长,每次减为原来的一半。 for (gap = n / 2; gap > 0; gap /= 2) { // 共gap个组,对每一组都执行直接插入排序 for (i = 0 ;i < gap; i++) { for (j = i + gap; j < n; j += gap) { // 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。 if (a[j] < a[j - gap]) { int tmp = a[j]; int k = j - gap; while (k >= 0 && a[k] > tmp) { a[k + gap] = a[k]; k -= gap; } a[k + gap] = tmp; } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13
voidshellsort(int arr[], int n){ for (int gap = n; gap >= 1; gap /= 2) { for (int i = gap; i < n; i += gap) { int temp = arr[i]; int pre = i - gap; while (pre >= 0 && arr[pre] > temp) { arr[i] = arr[pre]; pre -= gap; } arr[pre + gap] = temp; } } }
归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
voidMerge(int arr[], int n) { int temp[n]; // 用一个额外的数组来进行排序 int b = 0; // 额外数组的起始位置 int mid = n / 2; // mid将数组从中间划分,前后两半都有序 int first = 0, second = mid; // 两个有序序列的起始位置 //以下操作类似于将两个数组合并为一个有序数组 while (first < mid && second < n) { if (arr[first] <= arr[second]) // 比较两个序列 //这步操作相当于把第一个数组的值放到用来排序的数组,接着两个指针后移对下一个值进行操作 temp[b++] = arr[first++]; else temp[b++] = arr[second++]; }
while(first < mid) // 将剩余子序列复制到辅助序列中 temp[b++] = arr[first++]; while(second < n) temp[b++] = arr[second++]; for (int i = 0; i < n; ++i) // 辅助序列复制到原序列 arr[i] = temp[i]; }
voidMergeSort(int arr[], int n) { if (n <= 1) // 递归出口 return; if (n > 1) { MergeSort(arr, n / 2); // 对前半部分进行归并排序 MergeSort(arr + n / 2, n - n / 2); // 对后半部分进行归并排序 Merge(arr, n); // 归并两部分 } }
voidQuicksort(int arr[], int low, int high){ if (low < high) { //双指针,一个指向数组起始,一个指向数组末尾 int i = low; int j = high; //将数组的第一个元素作为key寻找它的位置 //key找到它的位置后,以它为分界线,左右两个数组分治 int key = arr[i]; while (i < j) { //两个指针不相遇,且指针指向的值大于key时,不断左移 while (i < j && arr[j] >= key) j--; if (i < j) arr[i] = arr[j]; //两个指针不相遇,且指针指向的值小于key时,不断右移 while (i < j && arr[i] <= key) i++; if (i < j) arr[j] = arr[i]; } //将key放在适合的位置 arr[i] = key; //分治 Quicksort(arr, low, i - 1); Quicksort(arr, i + 1, high); } }