|
楼主 |
发表于 2003-4-30 20:52:30
|
显示全部楼层
就地归并排序算法的未做优化实现
[code:1]int imergesort(int p[], int n);
extern int insertsort(int p[], int n);
extern int appendsort(int p[], int m, int n);
extern int binarysearch(int p[],int n, int v, int *m);
static int exchange(int src[],int dest[],int n);
static int swapMergeSort(int p[], int swap[], int n, int count);
static int swapMerge(int work[], int swap[], int m, int n,int flag);
static int replaceMerge(int p[],int m, int q, int n);
#define IN 1
#define OUT 0
/*
* in-place 归并排序算法的始作俑者和优化实现请参见:
* http://www.diku.dk/hjemmesider/ansatte/jyrki/Experimentarium/
* 其优化的最终结果是“在理论上比高级版本的堆排序优越,在实际上
* 比常规的堆排序慢50%”。不稳定,不需要辅助空间。
* 余之实现意图说明标志性的方法而未做任何优化。
*/
int imergesort(int p[], int n)
{
int op=0;
int i;
int k=n; /* 在头部的未排序的元素数目 */
int m=0; /* 在尾部的已排序的元素数目 */
i=k/2;
/* 用列表的前半部分做交换空间,
* 对列表的后半部分做归并排序。*/
op+=swapMergeSort(&p[n-i],p,i,0);
m=m+i;
k=k-i;
while(k>4) {
i=k/2;
/* 用未排序子列表的后半部分做交换空间,
* 对未排序子列表的前半部分做归并排序*/
op+=swapMergeSort(p,&p[i],i,0);
/* 把新排序出来的子列表与早先排序出来
* 的子列表做不对称归并,它们之间的未
* 排序空间被置换到列表头部。*/
op+=replaceMerge(p,i,n-m,m);
/* 列表的头部是未排序的,而尾部是已排序的 */
m=m+i;
k=k-i;
}
/* 最后的剩下的几个元素直接插入到已排序的列表中 */
if(k<m)
op+=appendsort(p,k,n);
else /* 整个列表只有几个元素的时候 */
op+=insertsort(p,n);
return op; /* 返回操作数 */
}
/*
* 前提:0 -> m-1 和 q -> q+n-1 是两个有序列表,
* 中间从 m -> q-1 是大小为 q-m 的未排序的空间。
* 要求 q>=2*m,即中间的未排序空间大于等于左面的列表。
* 结果:归并出从 q-m 开始的大小是 m+n 的有序列表,
* 0 到 q-m-1 是被置换出来的大小是 q-m 的未排序的空间。
*/
static int replaceMerge(int p[], /* 要归并的列表即左列表的头位置 */
int m, /* 左列表的长度 */
int q, /* 右列表的头位置 */
int n) /* 右列表的长度 */
{
int op=0;
int i=0,j=0,t=0;
int w=n/m; /* 两个子列表大小的比 */
int r;
int *left=p;
int *right=&p[q];
int *dest=&p[q-m];
while (i<m && j<n) {
/* 把左列表的一个元素与右列表的 w 个元素中的最大值做比较 */
if (left[i]>=right[j+w-1]) {
/* 选择的左列表元素大于等于右列表的 m 个元素。*/
op+=exchange(&right[j],&dest[t],w);
t=t+w;
j=j+w;
}else{
/* 以左列表一个元素作为查找值在右列表的 w 个元素中找到小于
* 查找值的元素个数 */
op+=binarysearch(&right[j],w,left[i],&r);
if (r!=0) {
op+=exchange(&right[j],&dest[t],r);
t=t+r;
j=j+r;
}
op+=exchange(&left[i],&dest[t],1);
t++;
i++;
}
if (w>n-j)
w=n-j;
}
if (i<m)
op+=exchange(&left[i],&dest[t],m-i);
return op;
}
/*
* 交换过程,操作数是 2*n+1 而不是 3*n,但不保持目标列表的
* 原有次序,故只能用在有序列表与无序列表之间的交换。
*/
static int exchange(int src[],int dest[],int n)
{
int i,temp;
if (n==0)
return 0;
temp=dest[0];
for(i=0;i<n-1;i++) {
dest[i]=src[i];
src[i]=dest[i+1];
}
dest[i]=src[i];
src[i]=temp;
return 2*n+1;
}
static int swapMergeSort(int work[], int swap[], int n, int count)
{
int op=0;
int m;
count++;
m=n/2;
if(n<=8) {
op+=insertsort(work,n);
if (count%2==0)
op+=exchange(work,swap,n);
} else {
op+=swapMergeSort(work,swap,m,count);
op+=swapMergeSort(work+m,swap+m,n-m,count);
op+=swapMerge(work,swap,m,n,count);
}
return op;
}
static int swapMerge(int work[], int swap[], int m, int n, int flag)
{
int *src, *dest;
int i=0, j=m, t=0;
int temp;
flag%=2;
if (flag==OUT) {
src=work;
dest=swap;
}
else { /* flag==IN */
src=swap;
dest=work;
}
temp=dest[t];
while (i<m && j<n) {
if (src[i] <= src[j]) {
dest[t] = src[i];
t++;
src[i] = dest[t];
i++;
} else {
dest[t] = src[j];
t++;
src[j] = dest[t];
j++;
}
}
while (i<m) {
dest[t] = src[i];
t = t++;
if (t<n)
src[i] = dest[t];
else
src[i] = temp;
i = i++;
}
while (j<n) {
dest[t] = src[j];
t++;
if (t<n)
src[j] = dest[t];
else
src[j] = temp;
j++;
}
return 2*n+1;
}
[/code:1] |
|