最近複習了排序演算法,所以在這篇部落格裡總結一下。
這裡的八大排序有:氣泡排序、快速排序、直接插入排序、shell排序、選擇排序、堆排、歸併排序和基數排序。
因為基數排序沒看,所以下面只會出現前面7種排序,之後可能會加上把。。。
首先簡單分個類
交換:氣泡排序、快速排序
插入:直接插入排序、shell排序
選擇:選擇排序、堆排
分配:歸併排序、基數排序
下面就乙個乙個來看把。
演算法:從陣列末尾開始,兩個兩個比較,小的交換到前面,大的交換到後面,就像泡泡一樣,小的數慢慢交換到最前面
時間複雜度:平均 :o(n^2)最好:o(n)最壞:o(n^2)
空間複雜度:o(1)
穩定性:穩定
**:
void bubble_sort(int arr,int low,int high)
} }}
兩層迴圈,外迴圈為一共的趟數,因為一趟遍歷下來會有乙個最小的數排序完成,一共個n個數,只剩下最後乙個數的時候不用再走一趟了,所以是n-1趟。內迴圈為一趟遍歷,從最後兩個開始遍歷,兩個數中小的放前面,大的放後面,及前面的數大則進行交換。**中的***目的是記錄一趟遍歷中有沒有交換,如果沒有交換,那麼整個排序肯定也完成了,此時不用繼續迴圈了。
演算法:讓要排序數的左邊的數都小於它,右邊的數都大於它,遞迴這個過程,使得整個陣列有序。
時間複雜度:平均:o(n*log2n)最好:o(n*log2n)最差:o(n^2)
空間複雜度:o(log2n)~o(n)
穩定性:不穩定
**:
void insert_sort(int arr, int low, int high)//插入排序
}int partition(int arr, int low, int high)
arr[low] = pivotkey; //樞軸元素歸位。
return low;
}void quick_sort(int arr, int low, int high)
} else
insert_sort(arr, low, high);
}
在元素較少的時候用遞迴不適合,所以用了插入排序,插入排序下面還會提到。快排有兩部分組成,乙個主體函式和乙個分割函式,分割函式的任務:使待排序數左邊數都小於它,右邊數都大於它(實際上就是確定了這個數的位置),主體函式在對這個數的左右兩邊再次分割排序(也就是呼叫遞迴),最後整個陣列便都有序了。
演算法:將待排序數插入到已經有序的陣列中。
例如:剛開始時,第乙個元素可視為有序的,那麼將第二個數插入它,就能得到乙個有兩個有序數的陣列,再把第三個數插入這個有兩個有序數的陣列……以此類推完成排序。
時間複雜度:平均:o(n^2)最好:o(n)最壞:o(n^2)
空間複雜度:o(1)
穩定性:穩定
**:
void insert_sort(int arr,int low,int high)
arr[j + 1] = temp;//找到位置後插入
}}
總的過程就是從前往後排序,先把前面的排成有序陣列,再把無序的數和有序陣列比較,找到乙個位置插入。
演算法:插入排序的優化,再插入排序的基礎上加入了分組的概念,減少了待排序元素的個數
時間複雜度:平均:o(n^1.3)最好:o(n)最壞:o(n^2)
空間複雜度:o(1)
穩定性:不穩定
**:
void shell_sort(int arr, int low, int high)
arr[j + increase] = temp;
} } while (increase > 1);
}
演算法:把陣列中最小的選出來,放到最前面,迴圈這個過程
時間複雜度:平均:o(n^2)最好:o(n)最壞:o(n^2)
空間複雜度:o(1)
穩定性:不穩定
**:
void select_sort(int arr, int low, int high)
} if (min != i)//把最小值往前提
}}
過程比較簡單,用下標記錄最小值的位置,遍歷陣列,找到最小的值,交換到前面,排完就是從小到大的乙個陣列。
演算法:堆排序是排序演算法中比較難的乙個,需要進行模組化降低難度。抽象出3個動作:1)堆調整;2)構建最大堆;
3)堆排序。初始構建堆,在重建堆的反覆篩選。
時間複雜度:平均:o(n*log2n)最好:o(n*log2n)最壞:o(n*log2n)
空間複雜度:o(1)
穩定性:不穩定
//[low+1..high]符合最大堆,需要調整使得[low..high]符合最大堆。
void heap_adjust(int arr, int low, int high)
arr[parent] = sentry;
}//將[low..high]構建成最大堆
void make_heap(int arr, int low, int high)
}//結合構建最大堆函式和堆調整函式進行堆排序
void heap_sort(int arr, int low, int high)
}
主要通過heap_adjust()函式來構建大根堆,在這個函式中,會把陣列調整成每個父節點都大於它的孩子節點,這樣調整完成後,就會有根節點是陣列的最大值,通過這個來進行排序。
演算法:也是使用了分割的思想,以中間點為分割,前後兩部分比較,按大小放入另乙個輔助陣列,遞迴排序
時間複雜度:平均:o(n*log2n)最好:o(n*log2n)最壞:o(n*log2n)
空間複雜度:o(n)
穩定性:穩定
void two_way_merge(int sr, int tr, int low, int mid, int high)
else
}//如果sr[low..mid]有剩餘元素,進行處理。
while(i <= mid)
//如果sr[mid+1..high]有剩餘元素,進行處理。
while(j <= high) }
//將第乙個引數所代表的元素就地排序,tmp[low..high]是臨時空間。
//要求sr[low..high]與tmp[low..high]元素完全一樣。
void rmerge(int sr, int tmp, int low, int high)
else }
//歸併排序
void merge_sort(int arr, int n)
rmerge(arr, tmp, 0, n-1);
delete tmp; //釋放堆區記憶體。
}
八大排序演算法總結
1.直接插入排序 原理 將陣列分為無序區和有序區兩個區,然後不斷將無序區的第乙個元素按大小順序插入到有序區中去,最終將所有無序區元素都移動到有序區 完成排序。要點 設立哨兵,作為臨時儲存和判斷陣列邊界之用。實現 void insertsort node l,int length l i 1 l 0 ...
八大排序演算法總結
插入排序 1.直接插入排序 原理 將陣列分為無序區和有序區兩個區,然後不斷將無序區的第乙個元素按大小順序插入到有序區中去,最終將所有無序區元素都移動到有序區完成排序。要點 設立哨兵,作為臨時儲存和判斷陣列邊界之用。實現 void insertsort node l,int length int i,...
八大排序演算法總結
插入排序 1.直接插入排序 原理 將陣列分為無序區和有序區兩個區,然後不斷將無序區的第乙個元素按大小順序插入到有序區中去,最終將所有無序區元素都移動到有序區完成排序。要點 設立哨兵,作為臨時儲存和判斷陣列邊界之用。實現 void insertsort node l,int length int i,...