C++_經典排序演算法
阿新 • • 發佈:2019-01-05
1冒泡、2插入、3選擇、4快排、5堆排、6歸併、7希爾、8計數、9桶排、10基數。
//主要參考:以下兩個部落格總結 //https://blog.csdn.net/yushiyi6453/article/details/76407640 //https://blog.csdn.net/kellen_f/article/details/79029066 #include <iostream> using namespace std; template <class T> void swap(T* num, int i, int j){ T tmp; tmp = num[i]; num[i] = num[j]; num[j]= tmp; } //1.氣泡排序,時間複雜度O(n^2),空間複雜度O(1) template <class T> void BubbleSort(T *num, int size){ if(size <= 1) return; for(int i = 0; i < size; i++){ bool flag = false; for(int j = 0; j < size - i - 1; j++){ if(num[j] > num[j+1]){ swap(num, j, j+1); flag = true; } } if(!flag) return; //排好序則直接退出 } } //2.插入排序,時間複雜度O(n^2),空間複雜度O(1) template <class T> void InsertSort(T *num, int size){ if(size <= 1) return; for (int i = 1; i < size; i++){ T tmp = num[i]; int j; for(j = i - 1; j >= 0; j--){ if(tmp < num[j]) num[j + 1] = num[j]; else break; } num[j+1] = tmp; } } //3.簡單選擇排序,時間複雜度O(n^2),空間複雜度O(1) template <class T> void SelectSort(T *num, int size){ if(size <= 1) return; for(int i = 0; i < size; i++){ int min = num[i]; int min_index = i; for (int j = i + 1; j < size; ++j) { if(num[j] < min){ min = num[j]; min_index = j; swap(num, min_index, i); } } } } //4.快排,時間複雜度O(nlogn),空間複雜度O(n) //在陣列中隨機選一個數(預設陣列首個元素),陣列中小於等於此數的放在左邊, //大於此數的放在右邊,再對陣列兩邊遞迴呼叫快速排序,重複這個過程。 template <class T> void QuickSort(T *num, int s, int t){ if(t <= 0) return; T tmp = num[s]; int i = s; int j = t; if (s >= t) return; while(i < j){ while(i < j && num[j] > tmp) j--; num[i] = num[j]; while(i < j && num[i] < tmp) i++; num[j] = num[i]; } num[i] = tmp; QuickSort(num, s, i - 1); QuickSort(num, i + 1, t); } //5.堆排序,時間複雜度O(nlogn),空間複雜度O(nlogn) template <class T> void HeapAdjust(T *num, int i, int size){ // 調整以形成大頂堆 int child = 2 * i + 1;//左孩子節點下標 while(child < size){ if(child + 1 < size && num[child] < num[child + 1]) child++;//右孩子更大 if(num[child] > num[i]){ swap(num, child, i); i = child; child = 2 * i + 1; } else break;//滿足根大於左右孩子,結束調整大頂堆 } } template <class T> void HeapSort(T* num, int size){ if (size <=1 ) return; // 建立大頂堆 for(int i = size / 2 - 1; i >= 0; --i){ HeapAdjust(num, i, size); } // 取出堆頂,放到結尾,並重新調整堆 for (int i = size - 1; i > 0; --i){ swap(num, 0, i); HeapAdjust(num, 0, i); //第i個數據已經排序完成 } } //6.歸併排序,時間複雜度O(nlogn), 空間複雜度O(nlogn) template <class T> void Merge(T *num, int begin, int mid, int end){ if(begin >= end) return; T* tmp = new T[end - begin + 1]; int id1 = begin, id2 = mid + 1; //合併兩段 int i = 0; while(id1 <= mid && id2 <= end){ if(num[id1] <= num[id2]) tmp[i++] = num[id1++]; else tmp[i++] = num[id2++]; } // 繼續合併 while(id1 <= mid) tmp[i++] = num[id1++]; while(id2 <= end) tmp[i++] = num[id2++]; // 將臨時資料寫回 for(int j = 0; j < end - begin + 1; j++) num[begin + j] = tmp[j]; delete []tmp; } template<class T> void MergeSortway(T *num, int begin, int end){ if(begin < end){ int mid = (begin + end) / 2; MergeSortway(num, begin, mid); MergeSortway(num, mid + 1, end); Merge(num, begin, mid, end); } } template<class T> void MergeSort(T *num, int size){ if (size <= 1) return; MergeSortway(num, 0, size - 1); } //7.希爾排序,時間複雜度O(nlogn),空間複雜度O(1) template <class T> void ShellSort(T *num, int size){ // 簡單插入排序的改進 if(size <= 1) return; //增量div for(int div = size/2; div >= 1; div = div / 2){ //分成div組 for(int i = 0; i < div; ++i){ // 對每組進行插入排序 for(int j = i; j < size - div; j += div){ for(int k = j; k < size; k += div){ if(num[j] > num[k]) swap(num, j, k); } } } } } //8.計數排序,時間複雜度O(n+k),k是整數的範圍,空間複雜度O(n+k) void CountSort(int num[], int size){ /*- 找出待排序的陣列中最大和最小的元素 - 統計陣列中每個值為i的元素出現的次數,存入陣列C的第i項 - 對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加) - 反向填充目標陣列:將每個元素i放在新陣列的第C(i)項,每放一個元素就將C(i)減去1 */ if(size <= 1) return; int min = num[0]; int max = num[0]; for(int i = 1; i < size; ++i){ if (min > num[i]) min = num[i]; if (max < num[i]) max = num[i]; } int tmp_size = max - min + 1; int count_num[tmp_size]; for(int i = 0; i < size; ++i){ count_num[num[i] - min]++; } int index = 0; for(int i = 0; i < tmp_size; ++i){ while(count_num[i]-- > 0){ num[index++] = i + min; } } } //9. 桶排序,時間複雜度O(n),空間複雜度O(n) //計數排序是簡單而特殊的桶排序 /* 桶排序將[0,1)區間劃分為n個相同的大小的子區間,這些子區間被稱為桶。 然後將n個輸入元素分別放入各自的桶中。因為輸入時均勻獨立的,所以一般不會有很多數同時落在一個桶中的情況。 這樣,我們想對各個桶中的資料進行排序,然後遍歷每個桶,按照次序把各個桶中的元素列出來即可。 */ //10.基數排序,時間複雜度O(n*digit),空間複雜度O(n),digit數字的位數 /* * 數排序又稱為“桶子法”,從低位開始將待排序的數按照這一位的值放到相應的編號為0~9的桶中。 * 等到低位排完得到一個子序列,再將這個序列按照次低位的大小進入相應的桶中,一直排到最高位為止, * 陣列排序完成。 */ int main(){ int num[10] = {2, 5, 1, 3, 0, 7, 9, 8, 4, 6}; CountSort(num, 10); for(int i = 0; i < 10; i++) cout<<num[i]<<" "; return 0; }