日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[算法]——归并排序(Merge Sort)

發(fā)布時間:2025/4/9 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [算法]——归并排序(Merge Sort) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

歸并排序(Merge Sort)與快速排序思想類似:將待排序數(shù)據(jù)分成兩部分,繼續(xù)將兩個子部分進(jìn)行遞歸的歸并排序;然后將已經(jīng)有序的兩個子部分進(jìn)行合并,最終完成排序。其時間復(fù)雜度與快速排序均為O(nlogn),但是歸并排序除了遞歸調(diào)用間接使用了輔助空間棧,還需要額外的O(n)空間進(jìn)行臨時存儲。從此角度歸并排序略遜于快速排序,但是歸并排序是一種穩(wěn)定的排序算法,快速排序則不然。

所謂穩(wěn)定排序,表示對于具有相同值的多個元素,其間的先后順序保持不變。對于基本數(shù)據(jù)類型而言,一個排序算法是否穩(wěn)定,影響很小,但是對于結(jié)構(gòu)體數(shù)組,穩(wěn)定排序就十分重要。例如對于student結(jié)構(gòu)體按照關(guān)鍵字score進(jìn)行非降序排序:

// A structure data definition typedef struct __Student {char name[16];int score; }Student; // Array of students name : A B C D score: 80 70 75 70Stable sort in ascending order: name : B D C A score: 70 70 75 80Unstable sort in ascending order: name : D B C A score: 70 70 75 80

其中穩(wěn)定排序可以保證B始終在D之前;而非穩(wěn)定排序,則無法保證。

1)數(shù)組的歸并排序

歸并排序的思想實(shí)際上是一種分治法,即將待排序數(shù)據(jù)分成兩部分,分別對兩部分排序,然后將這兩部分合并。下面以非降序排序?yàn)槔?#xff1a;

// Split arr[] into two parts [begin,mid), [mid,end) // and using merge_core to merge this two parts // Total Time O(nlogn) void merge_sort(int arr[], int begin, int end) {if (end-begin < 2) return;int mid = (begin+end)>>1;merge_sort(arr,begin,mid);merge_sort(arr,mid,end);merge_core(arr,begin,mid,end); } // Time O(logn)

其中arr[]為待排序數(shù)組,對于一個長度為N的數(shù)組,直接調(diào)用merge_sort(arr,0,N);則可以排序。

歸并排序總體分為兩步,首先分成兩部分,然后對每個部分進(jìn)行排序,最后合并。當(dāng)然也可以分成三部分或其他,然而通常是分成兩部分,因此又稱為二路歸并。merge_core可以將兩個有序數(shù)組合并成一個,具體操作如圖所示:

/* merge core: combine two parts which are sorted in ascending order* arr[]: ..., 1, 4, 8, 2, 3, 7, 9, ...* begin__| |__mid |__end* part1: 1, 4, 8 part2: 2, 3, 7, 9 ** combination:* part1:[1] [4] [8]* part2: | [2] [3] | [7] | [9]* | | | | | | |* tmp :[1] [2] [3] [4] [7] [8] [9]** at last, copyback tmp to arr[begin,end)* */

合并的前提是,兩個數(shù)組已經(jīng)是有序的。其代碼為:

void merge_core(int arr[], int begin, int mid, int end) {int i=begin, j=mid, k=0;int *tmp = (int*)malloc(sizeof(int)*(end-begin));for(; i<mid && j<end; tmp[k++]=(arr[i]<arr[j]?arr[i++]:arr[j++]));for(; i<mid; tmp[k++]=arr[i++]);for(; j<end; tmp[k++]=arr[j++]);for(i=begin, k=0; i<end; arr[i++]=tmp[k++]);free(tmp); } // Time O(n), Space O(n)

其中第6,7兩行,將剩余的部分追加到tmp[]中,然后將tmp[]寫回到arr[]。因此,對于數(shù)組使用歸并排序,需要輔助空間O(n)。由于是尾部調(diào)用merge_core,當(dāng)然可以將其寫入到merge_sort尾部,這里為了思路清晰,將其分成兩部分書寫。

2)鏈表的歸并排序

事實(shí)上,歸并排序更適合對鏈表排序,因?yàn)樵诤喜蓚€鏈表時,不需要額外的輔助空間存儲,而且也不需要對數(shù)據(jù)拷貝,直接移動指針即可。唯一的不便是:需要每次尋找到鏈表的中間節(jié)點(diǎn),然后以此將該鏈表分割成兩部分。尋找中間節(jié)點(diǎn),可以定義兩個指針fast和Mid,fast每次移動兩步,mid每次移動一步,當(dāng)fast到鏈表尾部時,mid此時處于鏈表中間(不用考慮奇偶情況):

// Merge sort for single list as ascending order // single list node define typedef struct __ListNode {int val;struct __ListNode *next; }ListNode;// Merge sort for single list without head node ListNode *merge_sort(ListNode *head) {if (head==NULL || head->next==NULL) return head;ListNode *fast, *mid, H;// find mid node between head and endfor (H.next=head, fast=mid=&H; fast && fast->next;){mid = mid->next;fast = fast->next->next;}fast = mid->next;mid->next = NULL; // cut down mid part from head listmid = fast;head = merge_sort(head);mid = merge_sort(mid);return merge_core(head,mid); }

注意,找到鏈表的中間節(jié)點(diǎn)后,務(wù)必將其指向NULL,以保證確實(shí)將鏈表分成兩部分。然后將兩個鏈表head與mid進(jìn)行合并。由于合并后可能會修改鏈表頭結(jié)點(diǎn),因此要返回新的鏈表頭結(jié)點(diǎn)。下面是合并操作:

// merge single list without head node (ascending order) ListNode *merge_core(ListNode *i, ListNode *j) {ListNode H, *p;for (p=&H; i && j; p=p->next){if (i->val < j->val){p->next = i;i = i->next;}else{p->next = j;j = j->next;}}p->next = (i ? i:j);return H.next; }

鏈表合并時,不需要像數(shù)組那樣,直接可以將鏈表尾部p->next指向剩余的i或j,即可完成合并??梢钥闯?#xff0c;歸并排序更適合于對鏈表排序,而快速排序適合于數(shù)組排序。

?注:本文涉及的源碼:merge sort :?https://git.oschina.net/eudiwffe/codingstudy/blob/master/src/sort/mergesort.c

轉(zhuǎn)載于:https://www.cnblogs.com/eudiwffe/p/6254394.html

總結(jié)

以上是生活随笔為你收集整理的[算法]——归并排序(Merge Sort)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。