最近在看一部美劇《breaking bad》,從中領會了不少東西。回頭再看過去寫的博客,感覺真是很糟糕。真正自己的東西極少,大多數內容都是網上一搜一大堆的玩意,那么,這樣的博客寫着有什么意思呢?
從今往后,我的博客一定要寫進自己的思想,就算沒有創新,也一定要有獨立思考求解的過程。
這篇對自然歸並排序算法時間復雜度的分析便是第一篇。
對於普通歸並排序算法,我就不贅述了。任何一本算法書籍都有介紹,隨便用python寫了一筆:
class Merge(): def __init__(self): self.tmp_arr = [0,0,0,0,0,0,0,0,0,0,0,0] def merge(self, arr, start, mid, end): for i in range(start, end+1): self.tmp_arr[i] = arr[i] j = mid + 1 k = start for i in range(start, end+1): if k > mid: arr[i] = self.tmp_arr[j] j += 1 elif j > end: arr[i] = self.tmp_arr[k] k += 1 elif self.tmp_arr[j] < self.tmp_arr[k]: arr[i] = self.tmp_arr[j] j += 1 else: arr[i] = self.tmp_arr[k] k += 1 def sort(self, arr, start, end): if end <= start: return mid = start + (end - start) / 2 self.sort(arr, start, mid) self.sort(arr, mid + 1, end) self.merge(arr, start, mid ,end) mobj = Merge() arr = [5,3,4,7,1,9,0,4,2,6,8] mobj.sort(arr, 0, len(arr)-1) for i in range(len(arr)): print arr[i]
其時間復雜度為O(nlogn),歸並排序的比較是分層次來歸並的(第一次是兩兩歸並,之后再在第一次歸並的基礎上兩兩歸並,每一層歸並的次數為上一層除二,最終形成一二叉樹,該二叉樹的高即為歸並次數logn。而每一層的比較次數恆等於n,所以時間復雜度求得nlogn)。
自然歸並排序算法是在歸並排序算法基礎上的改進,首先將數列中,已經有序的數分為小組,再在這些小組的基礎上歸並。
例如 5,3,4,7,1,9,0,4,2,6,8
則可首先得到{5},{3},{4,7},{1,9},{0,4},{2,6,8}
第一次歸並得到{3,5},{1,4,7,9},{0,2,4,6,8}
第二次歸並得到{1,3,4,5,7,9},{0,2,4,6,8}
可以看出,原理同樣是二路歸並,只不過最開始現將有序的部分划分了下。所以那一次‘划分了’多少個組,將決定以后的歸並是否更順利(樹的層數更少)
普通歸並排序的情況,第一次歸並得到的組數為g = N/2
自然歸並排序的情況,設第一次歸並得到的組數為g,因為,一個數為一組的概率為1/2,兩個數為一組的概率為1/4,n個數為一組的概率為2的n次方分之一。則可求得等式:

繼續推導:

可知,在隨機情況下,自然歸並排序分的組數是與普通歸並排序 無限趨近相等的。
結論:在分組數相等的基礎上,繼續進行二路歸並,之后的‘二叉樹’的高度便是一樣的。所以時間復雜度同樣為O(nlogn)。
然而,若已知待排序數列相對有序的情況,則自然歸並排序算法是優於普通歸並排序算法的。
