-
八種基本的排序(1)——冒泡排序(C語言實現)
八種基本的排序(2)——直接選擇排序(C語言實現)
八種基本的排序(3)——插入排序(C語言實現)
八種基本的排序(4)——歸併排序(C語言實現)
八種基本的排序(5)——快速排序(C語言實現)
目錄
快速排序(quick-Sort)
是對冒泡排序的一種改進。1
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
算法介紹
設要排序的數組是 ,首先任意選取一個數據(通常選用數組的第一個數)作爲關鍵數據,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱爲一趟快速排序。值得注意的是,快速排序不是一種穩定的排序算法,也就是說,多個相同的值的相對位置也許會在算法結束時產生變動。
一趟快速排序的算法是:
1)設置兩個變量 、 ,排序開始的時候: , ;
2)以第一個數組元素作爲關鍵數據,賦值給 ,即 ;
3)從 開始向前搜索,即由後開始向前搜索 ,找到第一個小於 的值 ,將 和 互換;
4)從 開始向後搜索,即由前開始向後搜索 ,找到第一個大於 的 ,將 和 互換;
5)重複第 、 步,直到 ; ( , 步中,沒找到符合條件的值,即 中 不小於 , 中 不大於 的時候改變 、 的值,使得 , ,直至找到爲止。找到符合條件的值,進行交換的時候 , 指針位置不變。另外, 這一過程一定正好是 或 完成的時候,此時令循環結束)。
排序演示
示例
假設用戶輸入瞭如下數組:
下標 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
數據 | 6 | 2 | 7 | 3 | 8 | 9 |
創建變量 (指向第一個數據), (指向最後一個數據), (賦值爲第一個數據的值)。
我們要把所有比 小的數移動到 的左面,所以我們可以開始尋找比 小的數,從 開始,從右往左找,不斷遞減變量 的值,我們找到第一個下標 的數據比 小,於是把數據 移到下標 的位置,把下標 的數據 移到下標 ,完成第一次比較:
下標 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
數據 | 3 | 2 | 7 | 6 | 8 | 9 |
, ,
接着,開始第二次比較,這次要變成找比 大的了,而且要從前往後找了。遞加變量 ,發現下標 的數據是第一個比 大的,於是用下標 的數據 和 指向的下標 的數據的 做交換,數據狀態變成下表:
下標 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
數據 | 3 | 2 | 6 | 7 | 8 | 9 |
, ,
稱上面兩次比較爲一個循環。
接着,再遞減變量 ,不斷重複進行上面的循環比較。
在本例中,我們進行一次循環,就發現 和 “碰頭”了:他們都指向了下標 。於是,第一遍比較結束。得到結果如下,凡是 左邊的數都比它小,凡是 右邊的數都比它大:
下標 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
數據 | 3 | 2 | 6 | 7 | 8 | 9 |
如果 和 沒有碰頭的話,就遞加i找大的,還沒有,就再遞減 找小的,如此反覆,不斷循環。注意判斷和尋找是同時進行的。
然後,對 兩邊的數據,再分組分別進行上述的過程,直到不能再分組爲止。
注意:第一遍快速排序不會直接得到最終結果,只會把比 大和比 小的數分到 的兩邊。爲了得到最後結果,需要再次對下標 兩邊的數組分別執行此步驟,然後再分解數組,直到數組不能再分解爲止(只有一個數據),才能得到正確結果。
調用函數
在c++中可以用函數qsort()可以直接爲數組進行排序。 2
用 法:
void qsort(void base, int nelem, int width, int (*fcmp)(const void ,const void *));
參數:
1 待排序數組首地址
2 數組中待排序元素數量
3 各元素的佔用空間大小
4 指向函數的指針,用於確定排序的順序
源代碼+註釋
//快速排序(我把它做成了一個小程序,大家複製下來運行)
//感謝百度百科,本程序借鑑了一下
#include<stdio.h>
#include<string.h> //字符串頭文件
int a[1000001]; //在主函數外面定義數組可以大一點(很多很多)
void kuaisu_sheng(int left,int right)
{
if(left>=right) //如果左邊索引大於或者等於右邊的索引就代表已經整理完成一個組了
return ;
int i=left; //將區間記錄下來
int j=right;
int key=a[i]; //記錄參考值
while(i<j) //控制在當組內尋找一遍
{
while(i<j&&key<=a[j]) //而尋找結束的條件就是,1,找到一個小於或者大於key的數(大於或小於取決於你想升序還是降序)2,沒有符合條件1的,並且i與j的大小沒有反轉
j--; //向前尋找
a[i]=a[j]; //找到一個這樣的數後就把它賦給前面的被拿走的i的值(如果第一次循環且key是a[left],那麼就是給key)
while(i<j&&key>=a[i]) //這是i在當組內向前尋找,同上,不過注意與key的大小關係停止循環和上面相反,因爲排序思想是把數往兩邊扔,所以左右兩邊的數大小與key的關係相反
i++;
a[j]=a[i];
}
a[i]=key; //當在當組內找完一遍以後就把中間數key迴歸
kuaisu_sheng(left,i-1); //最後用同樣的方式對分出來的左邊的小組進行同上的做法
kuaisu_sheng(i+1,right); //用同樣的方式對分出來的右邊的小組進行同上的做法
//當然最後可能會出現很多分左右,直到每一組的i = j 爲止
}
void kuaisu_jiang(int left,int right)
{
if(left>=right)
return ;
int i=left;
int j=right;
int key=a[i];
while(i<j)
{
while(i<j&&key>=a[j]) //順序這裏改
j--;
a[i]=a[j];
while(i<j&&key<=a[i]) //還有這裏(不清楚怎麼改可以對照上面升序的函數)
i++;
a[j]=a[i];
}
a[i]=key;
kuaisu_jiang(left,i-1);
kuaisu_jiang(i+1,right);
}
int main()
{
int n,m,i,choice;
printf("快速排序小程序(By STY)\n\n");
printf("升序還是降序\n");
printf("升序選“1 ”\n");
printf("降序選“2 ”\n");
printf("請輸入:(1~2)\n");
printf("退出請按“Ctrl+Z ”(在鍵盤上),並按回車,謝謝使用!\n");
while(scanf("%d",&choice)!=EOF)
{
memset(a,0,sizeof(a)); //清空數組
printf("請輸入要排序的數字個數:\n");
scanf("%d",&n);
printf("請輸入%d個數字:\n",n);
if(choice==1)
{
for(int ii=0;ii<n;ii++)
scanf("%d",&a[ii]);
kuaisu_sheng(0,n); //引用函數
printf("結果:\n");
for(i=1;i<n;i++) //循環輸出
printf("%d ",a[i]);
printf("%d(升序)\n\n\n\n",a[i]);
}
else if(choice==2)
{
for(int ii=0;ii<n;ii++)
scanf("%d",&a[ii]);
kuaisu_jiang(0,n);
printf("結果:\n");
for(i=0;i<n-1;i++)
printf("%d ",a[i]);
printf("%d(降序)\n\n\n\n",a[i]);
}
else
printf("開玩笑吧!\n");
printf("快速排序小程序(By STY)\n\n");
printf("升序還是降序\n");
printf("升序選“1”\n");
printf("降序選“2”\n");
printf("請輸入:(1~2)\n");
printf("退出請按“Ctrl+Z”(在鍵盤上),並按回車,謝謝使用!\n");
}
return 0;
}
//ENDING
普通版就不寫了,麻煩
希望大家喜歡這篇文章!!!
如有問題請留言,謝謝!!!
>>>我的博客<<<
- 部分摘自百度百科(點擊可進入) ↩
- 反正這裏是用C語言的,C++拿來拓展一下 >…< ↩