1.归并排序
归并排序(Merging Sort)就是利用归并思想实现的排序方法。它的原理就是假设初始序列含有n个记录,则可以看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,...如此重复,直至得到一个长度为n的有序序列为止。
递归方法的归并排序,代码如下:
void Merge(int* dest, int* src, int left, int mid, int right)//合并 { int i = left, j = mid + 1; int k = left; while (i <= mid && j <= right) { dest[k++] = src[i] < src[j] ? src[i++] : src[j++]; } while (i <= mid) { dest[k++] = src[i++]; } while (j <= right) { dest[k++] = src[j++]; } } void Copy(int* dest, int* src, int left, int right)//复制 { for (int i = left; i <= right; ++i) { dest[i] = src[i]; } } void MergePass(int* tmp, int* nums, int left, int right)//排序 { if (left < right) { int mid = (right - left) / 2 + left; MergePass(tmp, nums, left, mid); MergePass(tmp, nums, mid + 1, right); Merge(tmp, nums, left, mid, right); Copy(nums, tmp, left, right); } } void MergeSort(int* nums, int n)//归并排序 { if (nums == nullptr || n < 2) return; int* tmp = new int[n]; MergePass(tmp,nums, 0, n - 1); delete[]tmp; } int main() { int ar[] = { 56,23,78,45,99,85,12,34,67,99,100 }; int n = sizeof(ar) / sizeof(ar[0]); MergeSort(ar, n); for (int i = 0; i < n; ++i) { cout << ar[i] << " "; } cout << endl; }
运行结果:
归并算法的非递归实现
void Merge(int* dest, int* src, int left, int mid, int right)//合并函数 { int i = left, j = mid + 1; int k = left; while (i <= mid && j <= right) { dest[k++] = src[i] < src[j] ? src[i++] : src[j++]; } while (i <= mid) { dest[k++] = src[i++]; } while (j <= right) { dest[k++] = src[j++]; } } void MergePass(int* dest, int* src, int n, int s)//排序实现 { int i = 0; while (i + 2 * s - 1 <= n - 1)//合并的每一组数据都是2的幂次方 { Merge(dest, src, i, i + s - 1, i + 2 * s - 1); i = i + 2 * s; } if (n - 1 >= i + s)//合并的两组数据不是2的幂次方 { Merge(dest, src, i, i + s - 1, n - 1); } else//合并的两组数据一组为空 { for (int j = i; j < n; j++)//for循环把无法参与并轨的数据放到dest中 { dest[j] = src[j]; } } } void MergeSort(int* nums, int n)//合并排序 { int* tmp = new int[n]; int s = 1; while (s < n) { MergePass(tmp, nums, n, s);//nums数组合并排序后放到tmp数组中 s += s;//2 MergePass(nums, tmp, n, s);//tmp数组合并排序后放到nums数组中 s += s;//4 } delete[]tmp; } int main() { int ar[] = { 56,23,78,45,99,85,12,34,67,99,100 }; int n = sizeof(ar) / sizeof(ar[0]); MergeSort(ar, n); for (int i = 0; i < n; ++i) { cout << ar[i] << " "; } cout << endl; }
2.堆排序
1.创建堆:(大根堆)从中间结点开始,中间结点一定在倒数第二层,提高效率
2.排序:把第一个结点和最后一个结点交换,结点个数减一代码如下:
void CH(int* arr, int root, int n)//创建大根堆 { int i = 2 * root;//root*2==n此节点只要一个孩子且是左孩子,root*2>n此节点是叶子结点,root*2<n此节点有两个孩子 int t = arr[root]; while (i <= n) { if (i < n) { if (arr[i] < arr[i + 1])//先比较左右孩子的大小,找到最大的孩子 { i++; } } if (t >= arr[i]) break;//如果根结点比两个孩子大,已经是大根堆,不用变了 else//如果根结点没有孩子大,就交换 { arr[i / 2] = arr[i]; i = 2 * i; } } arr[i / 2] = t;//根结点 } void Heapsort(int* arr, int n)//堆排序 { int i, t; for (i = n / 2; i >= 1; i--)//从中间结点,开始创建大根堆 { CH(arr, i, n); } for (i = n; i >= 1; --i)//最后一个结点和第一个结点交换 { t = arr[1]; arr[1] = arr[i]; arr[i] = t; CH(arr, 1, i - 1);//交换完去掉最后一个结点,再创建大根堆 } } void main() { int arr[] = { 0,6,5,7,8,9,0,1,2,3,4,5,6,7 }; int n = sizeof(arr) / sizeof(arr[0]) - 1; Heapsort(arr, n); for (int i = 0; i < n; i++) { cout << arr[i] << " "; } }
运行结果:
3.快速排序
递归形式下的快排
void printfint(char* nums, int n) { for (int i = 0; i < n; i++) { printf("%5d ", nums[i]); } printf("\n"); } int partition(char*nums,int left,int right)//划分 { int i = left; int j = right; int temp = nums[i]; while (i < j) { while (i<j && nums[j]>temp) --j; if (i < j) nums[i] = nums[j]; while (i < j && nums[i] <= temp) i++; if (i < j) nums[j] = nums[i]; } nums[i] = temp; return i; } int Randompartition(char* nums,int left,int right)//随机划分方案 { srand(time(NULL)); int rapos = rand() % (right - left + 1)+ left; std::swap(nums[left],nums[rapos]); return partition(nums, left, right); } void QuickSort(char*nums,int left,int right)//排序 { if (left < right) { int mid = partition(nums, left, right); } } int main() { char nums[] = { 56,12,23,45,56,67,78,89,90,24 }; int n = sizeof(nums) / sizeof(nums[0]); printfint(nums, n); QuickSort(nums, 0,n-1); printfint(nums, n); }
运行结果:
非递归的快排
void printfint(char* nums, int n) { for (int i = 0; i < n; i++) { printf("%5d ", nums[i]); } printf("\n"); } void onewaysort(char* nums, int left,int right)//排序 { int i = left + 1; int j = left; int tmp = nums[left]; while (i <= right) { if (nums[i] <= tmp) { j++; std::swap(nums[i], nums[j]); } i++; } std::swap(nums[j], nums[left]); } int main() { char nums[] = { 56,12,23,45,67,78,89,90,24 }; int n = sizeof(nums) / sizeof(nums[0]); int left = 0; int right = n - 1; printfint(nums, n); onewaysort(nums, left, right); printfint(nums, n); }
运行结果:
07-03
2551
08-06
1657
07-13
404