堆排序的核心是把陣列看作乙個完全二叉樹,通過入堆操作把整個二叉樹整理一遍,使所有的父節點都比其子節點大,如此根節點a(即陣列的第一位)就是最大的數。把根節點a與二叉樹最後一位z調換,稱為a的出堆,即a已經排序完成。再處理被換上去的z,由於所有的父節點都比子節點大,只要把根節點下面子節點較大的那一位換到根節點,而根節點上的z就重複的進行處理沉下去,直到沉到底。重複出堆的操作,就可以得到公升序排列的陣列。整個操作的時間複雜度為o(nlog(n)),空間複雜度為o(1)。
從根節點開始,判斷其與父節點的大小關係,如果比父節點大,就與父節點交換,交換完成後繼續與新的父節點作比較。而根節點沒有父節點就不進行操作。
將根節點與二叉樹最後一片葉交換,並且二叉樹的節點減一,即原先的根節點已經排序完成,退出比較。再把新的根節點通過與子節點比較交換一路沉下去。需要注意的是由於排好序的節點已經退出比較,所以要注意更新子節點是否存在,否則會把已經排序完成的數喚醒。
規律:畫出乙個完全二叉樹並且標號(根節點標號為1)會發現任何乙個父節點k的子節點為2k和2k+1,有這樣的位置關係容易比較。
#include#include#define n 21
void enheap(int *a,int n);
void outheap(int *a,int n,int count);
void heap_sort(int *a,int n)
return;
}void enheap(int *a,int n)
return;
}void outheap(int *a,int n,int count) //count數記錄目前排序未完成的個數,若超出此數則說明觸碰了已排序完成的數
return;
}int main(void)
; for(i=1;i<=n;i++)
a[i]=rand()%n;
/*for(i=1;i歸併排序和快速排序在將排序陣列遞迴劃分成兩段上有一點點像,但快速排序是根據乙個關鍵數將資料分成兩段,遞迴過程中是先處理大的資料再劃分處理小的資料量。而歸併排序是將所有的資料先不斷遞迴劃分,直到乙個數字單元,再處理該段資料,然後返回,處理的資料量是從小到大的。而且歸併排序需要乙個額外的空間。但是快速排序在最壞情況下時間複雜度會退化到o(n*n),歸併不會存在這個問題。
1.原理:
將所有的資料遞迴劃分成兩段,直到單個資料不可分。然後再把兩兩相鄰的陣列合併。合併完之後得到的陣列再次合併,直到整個陣列合併。
2.**部分:#include #include #include #define n 1000000
int temp[n];
void merge(int *a,int *b,int n,int m) //將兩個陣列合併到temp陣列中
merge(a,a+n/2,n/2,n-n/2); //此處第一次處理的話就是兩個單個數合併
memcpy(a,temp,n*sizeof(int));
return;
}int main(void)//測試**
; int i=0;
for(i=0;i
堆排序,歸併排序
1.介紹 對簡單的選擇排序的一種改進,改進效果非常明顯,每次在選擇最小記錄的同時,並根據比較結果對其他記錄做出相應的調整,那麼排序效率就會提高很多。定義 將待排序的序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將它移走 其實就是將其與堆陣列的末尾元素進行交換,此時末尾元素就是最大值 ...
歸併排序和堆排序
歸併排序的演算法我們通常用遞迴實現,先把待排序區間 s,t 以中點二分,接著把左邊子區間排序,再把右邊子區間排序,最後把左區間和右區間用一次歸併操作合併成有序的區間 s,t 桶排序法,非常耗空間。規定陣列中元素的最大值不超過陣列的長度,否則要先求出陣列元素的最大值後,才能指定空桶的個數,要求待排序陣...
堆排序和歸併排序
極少涉及,在此就不再研究 了!堆排序 原理 把待排序的元素按照大小在二叉樹位置上排列,排序好的元素要滿足 父節點的元素要大於等於子節點 這個過程叫做堆化過程,如果根節點存放的是最大的數,則叫做大根堆,如果是最小的數,則叫做小根堆,可以把根節點拿出來,然後再堆化,迴圈到最後乙個節點。時間複雜度 平均 ...