霜降将至,气温有所下降,各位亲们注意保暖!不管天气如何,保持每天学习一点点,总会有新的收获
这两天继续在看C方面的书,在网上也看一些面试题方面的东西,为什么要看面试题,1. 当然为面试做准备 2. 面试题都是平时学C时容易忽略的,所以可以看看。
今天看了一下归并算法,其算法原理如下(文字来源于网络,原理理解就好^_^)
归并排序也是一种分割处理式的排序算法,它是由Johnyon Neumann于1945年提出的
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,归并排序将两个已排序的表合并成一个表。
归并排序基本原理
通过对若干个有序结点序列的归并来实现排序。
所谓归并是指将若干个已排好序的部分合并成一个有序的部分。
归并排序基本思想
设两个有序的子序列(相当于输入序列)放在同一序列中相邻的位置上:array[low..m],array[m +
1..high],先将它们合并到一个局部的暂存序列 temp (相当于输出序列)中,待合并完成后将 temp 复制回
array[low..high]中,从而完成排序。 在具体的合并过程中,设置 i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较 array[i] 和 array[j]
的关键字,取关键字较小(或较大)的记录复制到 temp[p] 中,然后将被复制记录的指针 i 或 j 加 1,以及指向复制位置的指针 p加
1。重复这一过程直至两个输入的子序列有一个已全部复制完毕(不妨称其为空),此时将另一非空的子序列中剩余记录依次复制到 array 中即可。
若将两个有序表合并成一个有序表,称为2-路归并。
举例说明会更清楚:
1.待排序列(14,12,15,13,11,16)
假设我们有一个没有排好序的序列,那么首先我们使用分割的办法将这个序列分割成一个个已经排好序的子序列。然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。
先"分割"再"合并"
从上图可以看出,我们首先把一个未排序的序列从中间分割成2部分,再把2部分分成4部分,依次分割下去,直到分割成一个一个的数据,再把这些数据两两归并到一起,使之有序,不停的归并,最后成为一个排好序的序列。
2.待排序列(25,57,48,37,12,92,86)
以上算法原理的文档出自这里,http://www.2cto.com/kf/201212/174207.html,当然网上还有一大堆关于这个算法的阐述的文档,如果有兴趣可以自己去查看,这里不引述了。
下面是用C完成的实验,编译环境:Dev C++ 4.9.9.2, 编程语言:C
#include
#include
typedef int RecType;
int test_tab[] = {0,4,9,5,7,1,3,9,6,4,5,6,7,7,8,8,1,0,3,2};
//将两个有序的子文件R[low..m)和R[m+1..high]归并成一个有序的子文件R[low..high]
void MergeArray(RecType *R,int low,int m,int high)
{
int i=low;
int j = m+1;
int p = 0;
RecType *R1; //R1是局部向量,需要动态分布内存,计算完成后,需要释放内存
R1 = (RecType *)malloc((high-low+1)*sizeof(RecType));
if(R1 == NULL)
return;
while(i<=m && j<=high)
R1[p++] = (R[i]>=R[j])?R[i++]:R[j++]; // 从大到小顺序排列
while(i<=m)
R1[p++] = R[i++];
while(j<=high)
R1[p++] = R[j++];
for(p=0,i=low;i<=high;p++,i++) //归并完成后将结果复制回R[low..high]
R[i] = R1[p];
free(R1);
R1 = NULL;
}
// 归并排序
void MergeSort(RecType R[],int low,int high)
{
// 用分治对R[low..high]进行二路归并排序
int mid;
if(low < high)
{
// 区间长度大于1
mid = (low+high)/2 ; // 分解
MergeSort(R,low,mid); // 递归地对R【low..mid】排序
MergeSort(R,mid+1,high); // 递归地对R【mid+1..high】排序
MergeArray(R,low,mid,high); // 组合,将两个有序区归并为一个有序列区
}
}
int main(int argc, char *argv[])
{
int i = 0;
int low=0,high=19;
int len = sizeof(test_tab)/sizeof(test_tab[0]);
printf("排列前的数组是:\r\n");
for(i=0;i
printf("%d ",test_tab[i]);
printf("\r\n排列 后的数组是:\r\n");
MergeSort(test_tab,0,len-1);
for(i=0;i
printf("%d ",test_tab[i]);
printf("\r\n");
system("PAUSE");
return 0;
}
好吧先写到这吧,关于打印结果,还是自己试一下吧,另外,不得不说一下,eeworld的论坛做的还算可以,可是博客做的真是不行,可能是由于不是主打产品的原因吧,博客的编辑不方便,好像也不怎么能上传附件,贴图也不是太方便,也没有world编辑功能,所以排版做的不太好……
俺觉得,虽然这个时代流行微信之类的短讯息,但是做为技术传承,博客要比论坛或微信更保留长久,更方便查阅,像论坛可能及时回答比较方便,像微信,看一下可能就过了,也只有博客,即方便自己做笔记,也方便他人阅读。像CSDN的博客就做的很好,而程序及电子类的工程师一般都有做笔记的习惯,这个与工作性质有关,所以不知道EEworld的团队能否把博客改进一下,谢谢!
不再闲扯,继续学习去……
最后,吼一下俺的口号:每天进步一点点,开心多一点^_^