1. 可按如下所述实现归并排序:假设序列中有k个长度为小于等于n的有序子序列。利用过程merge对它们进行两两归并,得到wps_clip_image-85个长度小于等于2n的有序子序列(wps_clip_image-128表示取整),称为一趟归并排序。反复调用一趟归并排序过程,使有序子序列的长度自n=1开始成倍地增加,直至使整个序列成为一个有序序列。试采用链表存储结构实现上述归并排序的非递归算法。函数原型如下:

void Linked_Mergesort(LinkedList &L);  //链表结构上的归并排序非递归算法

void Linked_Merge(LinkedList &L, LNode *p, Lnode *e1,Lnode *e2);

/*对链表上的子序列进行归并,第一个子序列是从p->next到e1,第二个是从e1->next到e2*/

答:

void Linked_Mergesort(LinkedList &L); //链表结构上的归并排序非递归算法

{ for(l=1;l<L.length;l*=2)

for(p=L->next,e2=p; p->next; p=e2)

{ for(i=1,q=p; i<=l && q->next; i++,q=q->next)

e1=q;

for(i=1; i<=l && q->next; i++,q=q->next)

e2=q;  //求两个待归并子序列的尾指针

if(e1!=e2)

Linked_Merge(L,p,e1,e2);

}

}

void Linked_Merge(LinkedList &L, LNode *p, Lnode *e1,Lnode *e2);

/*对链表上的子序列进行归并,第一个子序列是从p->next到e1,第二个是从e1->next到e2*/

{ q=p->next; //q和r为两个子序列的起始位置

r=e1->next; 

while(q!=e1->next && r!=e2->next)

{ if(q->data < r->data)

{ p->next=q;

p=q;

q=q->next; 

}

else

{ p->next=r;

p=r;

r=r->next; 

}

}

while(q!=e1->next)

  { p->next=q;

p=q;

q=q->next;

}

while(r!=e2->next)

  { p->next=r;

p=r;

r=r->next;

}

}

2.快速排序算法中,如何选取一个界值(又称为轴元素),影响着快速排序的效率,而且界值也并不一定是被排序序列中的一个元素。例如,我们可以用被排序序列中所有元素的平均值作为界值。编写算法实现以平均值为界值的快速排序方法。

解:题目解析:保存划分的第一个元素。以平均值作为枢轴,进行普通的快速排序,最后枢轴的位置存入已保存的第一个元素,若此关键字小于平均值,则它属于左半部,否则属于右半部。

int partition (RecType r[],int l,h)

{ int i=l,j=h,avg=0;

for(;i<=h;i++)  avg+=R[i].key;

i=l; 

avg=avg/(h-l+1); 

while (i<j) 

    { while (i<j &&R[j].key>=avg) j--;

      if (i<j) R[i]=R[j];

      while (i<j &&R[i].key<=avg) i++;

      if (i<j) R[j]=R[i];

     }

  if(R[i].key<=avg) return  i; 

else return  i-1;

}

void quicksort (RecType R[],int S,T);

{if (S<T)

   {  k=partition (R,S,T);

      quicksart (R,S,k); 

quicksart (R,k+1,T);

}

}

3.有一种简单的排序算法,叫做计数排序。这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键字互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键字比该记录的关键字小。假设对某一个记录,统计出数值为c,那么这个记录在新的有序表中的合适的存放位置即为c。

(1)给出适用于计数排序的数据表定义。

(2)编写实现计数排序的算法。

(3)对于有n个记录的表,比较次数是多少?

(4)与直接选择排序相比,这种方法是否更好?为什么?

解: 

(1) typedef struct

{ ElemType data;

KeyType key;

}listtype;

(2) void countsort(listtype a[],listtype b[],int n)

{int i,j,count;

for(i=0;i<n;i++)

{count=0;

for(j=0;j<n;j++)

if(a[j].key<a[i].key) count++;

b[count]=a[i];

}

}

(3) 对于有n个记录的表,关键字比较的次数是n2.

(4)直接选择排序比这种计数排序好,因为直接选择排序的比较次数为n*(n-1)/2,且可在原地进行排序(稳定排序),而计数排序为不稳定排序,需要辅助空间多,为O(n).

posted on 2009-11-15 15:49  yangjie  阅读(1060)  评论(0编辑  收藏  举报