請掃碼加公衆號,週三六定時更新
閒話不多說了,給出一個C語言實現的快速排序,快速排序部分主要源於C語言之父的黑皮書,因爲原書是對字符串進行排序的,我稍微改了一下弄成整型的。
#include<stdio.h>
#include<stdlib.h>
voidswap(int A[],int i,int j);
voidqsort1(int A[],int i,int j);
intmyrand(int left,int right);
intmain(void)
{
int A[10],i;
for(i=0;i<10;i++)
A[i]=myrand(0,99);
qsort1(A,0,9);
for(i=0;i<10;i++)
printf("%5d",A[i]);
}
intmyrand(int left,int right)
{
return(int)((rand()*1.0/RAND_MAX)*(right-left)+left);
}
voidqsort1(int A[],int left,int right)
{
int i,last,mid;
mid=(left+right)/2;
if(left>=right)
return ;
swap(A,left,mid);
last=left;
for(i=left+1;i<=right;i++)
if(A[i]<A[left])
swap(A,++last,i);
swap(A,left,last);
qsort1(A,left,last-1);
qsort1(A,last+1,right);
}
voidswap(int A[],int i,int j)
{
int temp;
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
main函數的工作分爲三部分,第一個for循環迭代爲數組賦予隨機值,然後qsort1()用來進行隨機排序,最後一個for循環則用來輸出數組。
跟隨在main函數後面的三個函數:myrand, qsort1, swap。 第一個用來製造給定區間的隨機整數, 第二個即是隨機排序(有個1是因爲我之前編譯了一個快速排序做自己的庫,不用在意那個1), 第三個函數用來交換數組中的兩個元素。
製造隨機整數的我就不贅述了,要是看不懂後臺私戳吧(這個函數很簡單,相信聰慧的你們一定能看懂)、
swap(intA[],int i,int j) 這個函數通過一個temp來交換A數組的第i個元素和第j個元素。
好了,開始介紹快速排序啦,瞪大眼睛
inti,last,mid; 三個整型變量,i用在後面的遍歷,mid則表示數組中間值,last用來說明最後樞紐元的位置(樞紐元是什麼請參考上上次推文)。
mid=(left+right)/2; left是數組第一個元素的下標,right是最後一個的,所以這個mid就能表示中間值的了。
A【3】=80也就是mid表示的值啦。
swap(A,left,mid);
這一條語句是把第一個元素和中間位置元素對換,目的是把中間元素做樞紐元。
爲什麼中間元素做樞紐元?
因爲在大多數情況下,我們會假定中間元素往往會接近序列的中值,用這個模擬的中值做樞紐元能將大約序列一半的元素分在樞紐元左邊,一半分在右邊。
這條語句結束後
爲什麼想接近一半分在左邊,一半分在右邊?
因爲這樣會使得快速排序接近最快情況,快速排序最理想的情況就是一半元素小於樞紐元,一半元素大於樞紐元。
for(i=left+1;i<=right;i++)
if(A[i]<A[left])
swap(A,++last,i);
在這個循環中,i從A【1】=5開始遍歷元素,把小於樞紐元A【0】=80的放在last左邊,
在對i=1以後
對i=2執行後,
直到最後i=6,last=6。last=7的原因是除了55-34的所有元素都小於80,所以last右邊沒有比80的值。
swap(A,left,last);
第一句swap將樞紐元放到last位置上。
接下來,原來七個元素的數組被分成了兩部分,一部分小於80,另一部分大於80(因爲沒有,所以假想後面還有元素把)
小於的部分其實就是從left到last-1,稱這部分爲A
而大於的部分則從last+1到right
接下來,我們分別遞歸A和B
qsort1(A,left,last-1);
qsort1(A,last+1,right);
第一句遞歸A部分,第二句話則遞歸B部分。
第一句和前面的過程基本類似。
第二句中因爲last+1=7>right=6,所以這一層的遞歸直接結束了,沒有進行任何操作。