快速排序原理及实现(c语言实现,超详细)
代碼是全的,全部復制粘貼就可以使用。用vs的小伙伴記得把scanf的_s安全檢查去掉哦。這是我的第一篇博客,如果有不足之處希望大家指正在留言區指正。
前言:
.
偶也是一個新手,在自學數據結構時了解到了這個排序算法,自己就產生了很濃厚的興趣然后就研究了一下,不過這個排序算法據說是面試常考的一個題目,以下是我個人的一些心得。冒泡排序和快排一樣,都是屬于交換類的排序, 快話不多說,先舉個栗子。
栗子:
比如我們對16,12,14,13,15這5個數進行快排(從小到大)。
變量說明:
low為數組下限位置,high為數組上限位置,important為待排序字符在排序完成的數列中的位置(即滿足左邊的數都小于他,右邊的數都大于他的位置)。
第一步:
.
先定義low=1和high=數組的長度,令important=low,先移動high(條件滿足情況下),將important處的數和high處的數進行比較,因為16>15,所以進行15和16交換,交換完成后開始移動low(條件滿足情況下),因為沒有數比16大,low會不斷+1所以最后high和low會停留在5這個位置上,5就是我們要找的位置,所以important最后=5,16在5位置時6的左邊的數都小于它,右邊的數都大于它。
| 排序后 | 15 | 12 | 14 | 13 | 16 |
| 初始 | low | high | |||
| 排序后 | low high |
第二步:
.
現在16的位置已經定了,我們開始對16的左半部分進行排序。我們先對15進行排序,使得15左邊的數都小于他,右邊的數都大于他,這個時候low=1和high=4,important=low, 先移動high(條件滿足情況下 ),同上,15和13進行交換,然后移動low,因為沒有數比15大,所以最后low=high=4,15在4位置時左邊的數都小于他,右邊的數都大于他。
| 排序后 | 13 | 12 | 14 | 15 | 16 |
| 初始 | low | high | |||
| 排序后 | low high |
第三步:
.
現在16,15的位置都已經定了,我們讓low=1,high=3,important=12,判
斷12<14,所以high-1,因為13>12,所以進行交換,13和12交換。13在2位置時,左邊的數都小于他,右邊的數都大于他。
| 排序后 | 12 | 13 | 14 | 15 | 16 |
| 初始 | low | high | |||
| 排序后 | low high |
第四步:
.
同上,但是不做任何交換。因為12已經滿足左邊的數小于他,右邊的數大于他。
| 排序后 | 12 | 13 | 14 | 15 | 16 |
| 初始 | low | high | |||
| 排序后 | low high |
快排的核心思想:
.
1.將每一個數都放置在一個正確的位置上,使得該數的左邊的所有數都小于他,右邊的所有數都大于他,當每個數都滿足這個條件時,數列排序完成。
2. 因為對每一步的處理有相似性,所以可以用遞歸和分治方法實現。
3. 將一個數組通過產生important拆分成2個小數組段,同時對這兩個數組進行排序,提高效率
代碼塊
1. 首先看一下要排序的數組的結構體
typedef struct data {int number[10];int length; }Data;2.定位important的代碼
int found_important(Data* p, int low, int high)//尋找中點 {int important;int temp;important = p->number[low]; while (low < high){while (low<high && important>p->number[high])//找右邊位置(控制排序方向)high--;temp= p->number[high];//交換數據,確保imporant的右邊都小于他p->number[high] = p->number[low];p->number[low] = temp;while (low<high && important<=p->number[low]) //找左邊位置(控制排序方向)low++;temp = p->number[high];//交換數據,確保imporant的左邊都大于他p->number[high] = p->number[low];p->number[low] = temp;}return low;//當low==high時,退出循環3遞歸確定每一個數的位置
void quickSort(Data *p,int low,int high) {int important;if (low < high){important = found_important(p, low, high);//記錄中點位置//分治思想quickSort(p, low, important-1);//確定左邊數列順序quickSort(p, important+1, high);//確定右邊數列順序} }4.main函數
int main()//快速排序(從大到小) {Data array;Data* p=&array;int i;//用于控制循環printf("請輸入要排序的數組個數\n");scanf_s("%d", &p->length);printf("請輸入待排序的數組\n");for (i = 1; i < p->length+1; i++){scanf_s("%d",&p->number[i]);}quickSort(p, 1, p->length);printf("數據排序后是:\n");for (i=1;i<p->length+1;i++){printf("%5d",p->number[i]);}return 0; }復雜度分析:
到這里就差不多結束了
我們現在來看一下程序的復雜度吧!
假設一個待排序的數組有n個元素
一次尋找important的循環需要遍歷數組一次,所以定位important的函數found_important的時間復雜度是O(n);
時間復雜度:
最好情況:
每一次都是對數組的對分,那么通過多個線程(提高速度的關鍵)對同時對子問題進行運算,那么就要運行log(以2為底) n次程序,所以最終的復雜度就是O(n×log(以2為底)n)。
最壞情況:
(上述栗子就是最壞情況)
每次的impotent都是子數組的最大或最小元素,使得數組無法被拆分運算,那么總共要運行n次,所以最終的時間復雜度為(n×n)。
平均上述情況,該算法的復雜度最終為O(n*log(以2為底)n)。
空間復雜度:
最好情況:
即快速排序的每一趟排序都將元素序列均勻地分割成長度相近的兩個子表,所需棧的最大深度為log2(n+1)。
最壞情況:
棧的最大深度為n。這樣,快速排序的空間復雜度為O(log2n))。
因為存在對數,所以當數據量很大時,快排的優勢就特別明顯了。
因此,該排序方法被認為是目前最好的一種內部排序方法。
參考資料:
1.快速排序百度百科
2.《大話數據結構》 -成杰著
總結
以上是生活随笔為你收集整理的快速排序原理及实现(c语言实现,超详细)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串的对比(python)
- 下一篇: mysql绿色版安装与卸载