归并排序(非递归) ----- C语言
归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
算法步骤:
1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4. 重复步骤3直到某一指针达到序列尾
5. 将另一序列剩下的所有元素直接复制到合并序列尾
以上理论归理论,代码要实现其实还是有难度的,自己搞了很久才基本弄清楚非递归的归并排序的基本思想,查阅许久才看懂代码,自己简单地实现了一下:
#define A_LENGTH 10 #include <stdio.h> #include <stdlib.h> int MergeSort(int *a) { int k = 1;/*k用来表示每次k个元素归并*/ int *temp = (int *)malloc(sizeof(int) * A_LENGTH); while (k < A_LENGTH) { //k每次乘以2是遵循1->2->4->8->16的二路归并元素个数的原则 MergePass(a, temp, k, A_LENGTH);/*先借助辅助空间归并*/ k *= 2; MergePass(temp, a, k, A_LENGTH);/*再从辅助空间将排过序的序列归并回原数组*/ k *= 2; } } int MergePass(int *S, int *T, int times, int length) { int i = 0, s = times, l; while ((i + 2*s - 1) < length) { Merge(S, T, i, i+s-1, i+2*s-1); i += 2*s; }/*此处的循环用于遍历数组全部元素并依照k(此处为赋值为s)来归并入辅助的数组空间中*/ /*if-else用于处理归并剩下的序列,因为已经不满足(i + 2*s - 1) < length的条件 * 所以需要修改Merge()函数的下标,而如果满足(i + s - 1) < length即表示 * i 到 i + s - 1 这段序列为归并的第一段,剩下一段为 i + s 到 length - 1, * 而如果不满足if条件则说明剩下序列已经有序,直接循环赋值给目标数组即可 */ if ((i + s - 1) < length) { Merge(S, T, i, i+s-1, length-1); } else { for (l = i; l < length; l++) { T[l] = S[l]; } } } //归并排序最主要实现函数 int Merge(int *S, int *T, int low, int m, int high) {//j在[m+1,high]区间递增,k用于目标T的下标递增, l是辅助变量 int j, k, l; for (k = low, j = m+1; low <= m && j <= high; k++) { if (S[low] < S[j]) { T[k] = S[low++]; //此处先执行T[k] = S[low],然后low++; } else { T[k] = S[j++]; //同理 } } //for循环过后,必然有low>m 或者 j>high,故分情况处理 if (low <= m) { for (l = 0; l <= m-low; l++) { T[k+l] = S[low+l]; } } if (j <= high) { for (l = 0; l <= high-j; l++) { T[k+l] = S[j+l]; } } } int main() { int i; int a[A_LENGTH] = {50, 90, 80, 40, 30, 120, 150, 200, 70, 60}; printf("Before sorting:"); for (i = 0; i < A_LENGTH; i++) { printf("%d -- ", a[i]); } MergeSort(a); printf(" After sorting: "); for (i = 0; i < A_LENGTH; i++) { printf("%d -- ", a[i]); } return 0; }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 非递归实现归并排序
- 下一篇: 归并排序的递归与非递归实现Java