W. :合并排序
来源:互联网 发布:淘宝哪些代购店是真的 编辑:程序博客网 时间:2024/05/21 08:01
//author: W.
//合并排序. 2.3-2 P22
//时间复杂度:O(nlgn)
#include <stdio.h>
#include <stdlib.h>
//#define USE_CONTINUE
void merge(int a[], int p, int q, int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int* L = (int*)malloc(sizeof(int) * n1);
int* R = (int*)malloc(sizeof(int) * n2);
int i;
int j;
int k;
for(i = 0; i < n1; ++i)
{
L[i] = a[p+i];
}
for(j = 0; j < n2; ++j)
{
R[j] = a[q+1+j];
}
i = 0; //循环不变式初始化:L[i]和R[i]分别是L与R中最小值,新的a中加入的元素个数为0,即加入的元素是L和R中的最小元素(还没有元素呢)
j = 0;
for(k = p; k <= r; ++k)//保持:L[i]和R[i]分别是L与R中最小值,新的a中加入的元素是L和R中的最小元素,即a中已加入元素都是小于L和R中的元素,在完成++k后,a[p]~a[k-1]为已排序
{
#ifdef USE_CONTINUE //使用该方式的好处是在循环不变式的主循环中会在循环结束后得到结果,即对循环不变式的终止情况判断清晰
//但这种方式会导致加入L或R剩余的元素时,每次都要多一次i == n1或 j == n2的判断
if(i == n1) //使用在主循环中处理完所有操作,注意由于n1 + n2 == r - p + 1,所以这里无需判断j < n2
{
a[k] = R[j];
++j;
continue;
}
else if(j == n2)
{
a[k] = L[i];
++i;
continue;
}
#endif
#ifndef USE_CONTINUE //如果L或R中某个数组读取完毕,则跳出循环,把剩余的加入到a[k]剩下的空间中
//但这种方式要求循环不变式的终止要推迟到外面的另一个循环完毕。
if((i == n1) || (j == n2))
{
break;
}
#endif
if(L[i] <= R[j])
{
a[k] = L[i];
++i;
}
else
{
a[k] = R[j];
++j;
}
}
#ifndef USE_CONTINUE
if(k <= r)
{
if(i == n1)
{
for(; k <= r; ++k)
{
a[k] = R[j];
++j;
}
}
else if(j == n2)
{
for(; k <= r; ++k)
{
a[k] = L[i];
++i;
}
}
}
#endif
//无论采用哪种方式,此时循环不变式到此终止,即k此时为r+1,则a[p]~a[r]已排序完毕
free(L);
free(R);
}
void merge_sort(int a[], int p, int r)
{
//分治法:
int q;
if(p < r)
{
q = (p + r) / 2; //向下取整 //分解:分解成子问题,即分解成2部分子序列
merge_sort(a, p, q); //解决:递归地解各个子问题。
merge_sort(a, q+1, r);
merge(a, p, q, r); //合并:将子问题的结果合并成,即将2部分子序列通过merge函数进行合并。
}
//当p >= r时,此时a[p] ~ a[r]至多只有一个元素,则处于已排序状态 //解决:若子问题足够小,直接求解。即这里已排序,无需做任何操作
}
void test_sort()
{
int a[] = { 5, 2, 4, 6, 1, 3, 10, 6, 7, 9, 8};
int i;
for(i = 0; i < sizeof(a)/sizeof(int); ++i)
{
printf("%d ", a[i]);
}
printf("/n");
merge_sort(a, 0, sizeof(a)/sizeof(int) - 1);
for(i = 0; i < sizeof(a)/sizeof(int); ++i)
{
printf("%d ", a[i]);
}
printf("/n");
}
int main(int argc, char** argv)
{
test_sort();
return 0;
}
//输出:
//5 2 4 6 1 3 10 6 7 9 8
//1 2 3 4 5 6 6 7 8 9 10
- W. :合并排序
- W. :利用合并排序和二分查找实现习题2.3-7
- W. :利用最小优先级队列实现对k个已序队列的合并排序。习题6.5-8
- W. :插入排序
- W. :选择排序
- W. :堆排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 合并排序
- 文本框禁止拖拽和粘贴
- Java进阶学习:jar打包详解
- windows映射模式
- ASWING 学习笔记2
- 代销商品
- W. :合并排序
- php找回密码功能
- 闭合浮动的几种常用方法
- Terasoluna框架讲解(带小例子)
- JavaScript在IE和Firefox(火狐)的不兼容问题解决
- SQL SERVER:在SQL中分类合并数据行
- Windows 映射模式
- 编程网站
- 存储引擎内幕:启动页校验和会丢弃页残损保护吗?