【每日函式】每日函式(2021.08.05)
阿新 • • 發佈:2021-08-05
一、演算法思想:
假設初始序列中含有N個記錄,則可以看成N個有序的子序列,每個子序列的長度為一,然後兩兩歸併,得到\([\frac{N}{2}]\)(表示不小於2的最小整數)個長度為2或者1的有序子序列:再兩兩歸併,如此重複,直到得到一個長度為N的有序子序列為止,稱為2路歸併排序(Merge Sort)。
二、演算法實現
1、遞迴實現
1)排序原理
歸併排序的遞迴實現主要在於遞迴分治,對於遞迴演算法,我們都能用二叉樹來理解,對於一個序列,遞迴左右子序列,並對其子序列進行合併排序,即可得到排序好的序列
排序過程圖示
2)程式碼實現
#include<stdio.h> #include<stdlib.h> #define N 10 void Merge(int sort[],int num[],int low,int mid,int high) { int i=low; //左子序列起點下標 int j=mid+1; //右子序列起點下標 int k=low; //臨時陣列的初始化下標 while(i<=mid&&j<=high)//在左右子序列中按從小到大順序存到臨時陣列中 { if(num[i]<num[j]) sort[k++]=num[i++]; else sort[k++]=num[j++]; } //將左右子序列剩餘的數依次存入臨時陣列 while(i<=mid) sort[k++]=num[i++]; while(j<=high) sort[k++]=num[j++]; //將臨時陣列的資料按位置複製到原陣列對應位置上 while(--k>=0) num[k]=sort[k]; } void MergeSort(int sort[],int num[],int low,int high) { if(low<high) { int mid=(low+high)/2; //分為左右子序列的中間下標 MergeSort(sort,num,low,mid); //遞迴左子序列 MergeSort(sort,num,mid+1,high); //遞迴右子序列 Merge(sort,num,low,mid,high); //排序 } } int main() { int *sort; int num[N]={5,3,7,1,9,2,0,4,8,6}; sort=(int*)malloc(N*sizeof(int)); MergeSort(sort,num,0,N-1); for(int i=0;i<N;i++) printf("%d ",num[i]); printf("\n"); free(sort); return 0; }
2、非遞迴實現
1)排序原理
歸併排序的非遞迴實現主要在於子序列的劃分;
1、首先需要一個臨時陣列以及左右兩個子序列的區間;
2、從區間長度為1開始(遞增兩倍)將原陣列劃分成多對左右兩個子序列;
3、依次將多對左右子序列進行比較,並按順序存入臨時陣列中
4、再將臨時陣列排序好的序列再複製到原陣列中
5、最後區間長度兩倍增長,重複以上操作,即歸併
排序過程圖示
2)程式碼實現
#include<stdio.h> #include<stdlib.h> #define N 10 void MergeSort(int num[],int len) { int i,j; int *sort; int L_start=0,L_end=0;//初始化左區間的起點、終點下標 int R_start=0,R_end=0;//初始化右區間的起點、終點下標 sort=(int*)malloc(N*sizeof(int));//為臨時陣列分配空間 for(i=1;i<N;i*=2)//區間長度兩倍遞增 { for(L_start=0;L_start<len-i;L_start=R_end) { //確定左右區間兩邊的起點、終點下標 L_end = L_start+i; R_start = L_start+i; R_end = R_start+i; if(R_end>len)//右區間終點不超過陣列長度 { R_end=len; } j=0; //臨時陣列初始下標 while(L_start<L_end && R_start<R_end) { //比較左右起點資料的大小,並將較小的資料依次存入臨時陣列 if(num[L_start]<num[R_start]) sort[j++]=num[L_start++]; else sort[j++]=num[R_start++]; //同時起點下標遞增 } while(L_start<L_end)//將比較完剩餘的資料存入臨時陣列 { sort[j++]=num[L_start++]; } while(j>0) //將已排好的臨時陣列資料錄入原陣列中 { num[--R_start]=sort[--j]; } //for(int k=0;k<len;k++) // printf("%d ",num[k]); //printf("\n"); } //printf("-------------\n"); } free(sort); } int main() { int num[N]={5,3,7,1,9,2,0,4,8,6}; MergeSort(num,N); for(int i=0;i<N;i++) printf("%d ",num[i]); printf("\n"); return 0; }