分治法排序
分治法思想:
将原问题分解为几个规模较小但类似与原问题的子问题,递归的求解这些子问题。
然后再合并这些子问题的解来建立原问题的解。
分治模式在每层递归时都有三个步骤:
分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
解决这些子问题,递归地求解各个子问题。然而,若子问题的规模足够小,则直接求解。
合并这些子问题的解成原问题的解。
模型:扑克牌
假设桌上有两堆牌面朝上的牌,每堆都已经排好序,最小的牌在顶上。
我们希望把这两堆牌合并成单一的排好序的输出堆,牌面朝下地放在桌上。
我们的基本步骤包括在牌面朝上的两堆牌的顶上两张牌中选取较小的一张,
将该牌从堆中移开(该堆的顶上显露一张新牌)并牌面朝下地将该牌放置到输出堆。
重复这个步骤,直到一个输入堆为空,这时,我们只是拿起剩余的输入堆并牌面朝下地将该堆放置到输出堆。
为了简化代码,在每个输入堆的底部放置一张哨兵牌,其值为 无穷大。
它不可能为较小的牌,除非两个输入堆都显露出哨兵牌。
但是一旦发生这种情况,所有非哨兵牌都已经被放置到输出堆。算法就停止了。
伪代码:
MERGE(A, p, q, r) n1=q-p+1 n2=r-q Let L[1..n1+1] and R[1..n2+1] be new arrays for i=1 to n1 L[i]=A[p+i-1] for j=1 to n2 R[j]=A[q+j] L[n1+1]=无穷大 R[n2+1]=无穷大 i=1 j=1 for k=p to r if L[i]<=R[j] A[k]=L[i] i=i+1 else A[k]=R[j] j=j+1
代码:
#include<stdio.h> #include<stdlib.h> void MERGE_SORT(int *A,int p,int r); void MERGE(int *A,int p,int q,int r); typedef struct Array { int num; struct Array *next; }array; array *head0,*tail0; array *head1,*tail1; int main(void) { head0=(array *)malloc(sizeof(array)); tail0=(array *)malloc(sizeof(array)); head1=(array *)malloc(sizeof(array)); tail1=(array *)malloc(sizeof(array)); int A[]={3,1,0,8,4,5,0,2,4,1,6,7,2,7,5,6,4,6,5}; int i,n=sizeof(A)/sizeof(A[0]); MERGE_SORT(A,0,n); for(i=0;i<n;i++) { printf("%2d",A[i]); } printf("\n"); return 0; } void MERGE_SORT(int *A,int p,int r) { int q; if(p<r) { q=(r+p)/2; MERGE_SORT(A,p,q); MERGE_SORT(A,q+1,r); MERGE(A,p,q,r); } } void MERGE(int *A,int p,int q,int r) { int i,j,k; int n1=q-p+1; int n2=r-q; array *p1,*p2; head0->next=tail0->next=NULL; head1->next=tail0->next=NULL; for(i=0;i<n1;i++) { p1=(array *)malloc(sizeof(array)); p1->num=A[p+i]; if(head0->next==NULL) { head0->next=p1; tail0=p1; } else { tail0->next=p1; tail0=p1; } tail0->next=NULL; } for(j=1;j<=n2;j++) { p2=(array *)malloc(sizeof(array)); p2->num=A[q+j]; if(head1->next==NULL) { head1->next=p2; tail1=p2; } else { tail1->next=p2; tail1=p2; } tail1->next=NULL; } p1=head0->next; p2=head1->next; for(k=p;k<=r;k++) { if(p1!=NULL) { if(p2==NULL || p1->num<=p2->num) { A[k]=p1->num; p1=p1->next; } else { A[k]=p2->num; p2=p2->next; } } else { A[k]=p2->num; p2=p2->next; } } p1=head0->next; p2=head1->next; while(p1) { array *p0; p0=p1; p1=p1->next; free(p0); } while(p2) { array *p0; p0=p2; p2=p2->next; free(p0); } }