分治排序演算法
阿新 • • 發佈:2018-11-11
週末閒著無聊,又把演算法導論的書翻出來看了一下,終於經過一天時間把困擾我許久的分治排序演算法做出來了。
分治演算法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。(百度百科)
假設有一個數組。未排序前是這樣的,若想進行分治排序,1.是將陣列分割,從圖上可以看出,對於n個元素的陣列,可以將其分割為log2(n)個不可分割小組。
2在分割好的陣列(只含有兩個元素或一個元素)排序,這裡採用的是升序排序。將兩個元素的位置交換即可。
3.合併陣列,將圖上兩個元素的數組合併成一個數組。由於兩個陣列已經是升序排列好的,只用一次遍歷這兩個元素即可。
下面是詳細的步驟圖:
附上原始碼:
include <stdio.h> include <stdlib.h> void swap(int& a,int& b ){ int t=a; a=b; b=t; } void combine(int *a,int start,int split,int end){ if(split-start==1 && end-split==1) return; int *b=(int*)malloc(sizeof(int)*(end-start)); int i=0,j=0; int k=0; for(;(i+j)!=(end-start);k++){ if(i!=split-start && j!=end-split){ if(a[start+i]>=a[split+j]){ b[k]=a[split+j]; j++; continue;//continue是保證每次k都能自增 } if(a[start+i]<a[split+j]){ b[k]=a[start+i]; i++; continue; } }else{ if(i==split-start){ b[k]=a[split+j]; j++; continue; }else{ b[k]=a[start+i]; i++; } } } for(i=0;i<end-start;i++){ a[start+i]=b[i]; } free(b); b=NULL; } void mergesort(int *a,int start,int split,int end){ if(split-start==1 && end-split==1){ if(a[start]>a[split]){ swap(a[start],a[split]); return; } } if((split-start)*(end-split)==0) return; int start1,split1,end1; if(split-start>1){ split1=start+(split-start)/2; end1=split; mergesort(a,start,split1,end1); combine(a,start,split1,end1); } if(end-split>1){ start1=split; split1=start1+(end-split)/2; mergesort(a,start1,split1,end); combine(a,start1,split1,end); } combine(a,start,split,end);//這步很必須,不然排序無法完成 } int main(){ int a[]={3,2,4,1,6,9,8,7,5,44, 32,54,23,56,876,54,23,45,34,67, 34,233,54,98,5,32,43,23,12,90, 78,65,43,32,21,56,43,32,56,43, 45,43,23,13,23,43,56,344,34,23}; mergesort(a,0,25,50); for(int i=0;i<50;i++) printf("%d ",a[i]); }
程式效果圖