插入排序
描述:
假设有一把扑克牌:7,2,10,4,6,9,K,4,J,Q,3,现在要对其进行排序。
从左往右开始,7是第一个,不动,从第二个(2)开始,2<7于是放到7前面:2,7,10,4,6,9,K,4,J,Q,3
接着10大于7,大于2,放回原位置不做调整。
2<4<7放到2的后面。
。。。
这样一直到最后一张3插入到2的后面。整个排序结束。
归并排序
描述:
如果要对序列7,2,10,4,3,9,K,4,J,Q,3排序可以将其分成两半7,2,10,4,6和9,K,4,J,Q,3对这两部分分别排序。
同样对7,2,10,4,6排序可将其分成两部分7,2和10,4,6
对7,2排序可以再分为两部分:7和2
然后将这两部分按照次序合并放入数组中:2,7。
同样数组2,7和6,4,10合并成2,3,4,7,10.
依次类推,2,4,6,7,10和3,4,9,J,Q,K合并成2,3,4,6,7,9,10,J,Q,K
代码实现:
#include "common.h"
extern void Sort();
static void InsertionSort(int* a,int n);
static void MergeSort(int* a,int p,int r);
static void Merge(int* a,int p,int q,int r);
void Sort()
{
int a[]= {19,3,12,4,7,6,12,9,23,14,29,13,34,8};
Debug(a,sizeof(a)/sizeof(int),0);
//InsertionSort(a,sizeof(a)/sizeof(int));
MergeSort(a,0,sizeof(a)/sizeof(int)-1);
Debug(a,sizeof(a)/sizeof(int),0);
}
static void InsertionSort(int* a,int n)
{
int j;
for(j=1;j<n;j++)
{
int key = a[j];
int i = j-1;
while(i>=0 && a[i]>key)
{
a[i+1] = a[i];
i--;
}
a[i+1] = key;
}
}
static void MergeSort(int* a,int p,int r)
{
int q=0;
if(p<r)
{
q = (r+p)/2;
MergeSort(a,p,q);
MergeSort(a,q+1,r);
Merge(a,p,q,r);
Debug(a,r-p+1,p);
}
}
static void Merge(int* a,int p,int q,int r)
{
int i=0,j=0;
int len = r-p+1;
int first1 = p,
last1 = q;
int first2 = q+1,
last2 = r;
int *t = (int*)malloc(len*sizeof(int));
if( t== NULL || len == 0)
{
return;
}
while(first1<=last1 && first2 <= last2)
{
if(a[first1] < a[first2])
{
t[i] = a[first1];
first1++;
i++;
}
else
{
t[i] = a[first2];
first2 ++;
i++;
}
}
while(first1 <= last1)
{
t[i] = a[first1];
first1++;
i++;
}
while(first2 <= last2)
{
t[i] = a[first2];
first2++;
i++;
}
for(i=p,j=0; i<=r; j++,i++)
{
a[i] = t[j];
}
free(t);
}
尽管合并排序的最坏情况运行时间为Θ(n*lgn),插入排序的最坏情况运行时间为Θ(n平方),但插入排序中的常数因子使得它在n较小时,运行的要更快一些。因此在合并排序算法中,当子问题足够小时,采用插入排序就比较合适了。最坏情况运行时间为Θ(nk+nlg(n/k))
static void MergeSort(int* a,int p,int r)
{
int q=0;
if(r-p>=7)
{
q = (r+p)/2;
MergeSort(a,p,q);
MergeSort(a,q+1,r);
Merge(a,p,q,r);
}
else
{
InsertionSort(a+q,r-q+1);
}
Debug(a,r-p+1,p);
}