常用排序算法之快速排序

快速排序最坏情况运行时间为O(n2),但实际中通常都是用于排序的最佳的实用选择,因为其平均性能相当好:期望的运行时间为O(nlgn),且O(nlgn)记号中隐含的常数因子很小。

快速排序是一种就地排序。同时,是一种不稳定的排序。本文内容主要参照算法导论。

 

快速排序主要利用了分治的思想。一般分为三步进行:

分解:数组A[p..r]被划分为两个子数组A[p..q-1]和A[q+1..r],其中A[p..q-1]的元素都小于等于A[q],A[q+1..r]都大于等于A[q]。

解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序。

合并:因为两个子数组是就地排序的,将它们合并不需要额外操作,整个数组已经是排好序的。

下面是快速排序的C语言代码:

 1 int QuickSort(int *A,int p, int r)
 2 {
 3     if(p<r)
 4     {
 5         int q;
 6         q=Partition(A,p,r);
 7         QuickSort(A,p,q-1);
 8         QuickSort(A,q+1,r);
 9     }
10 }

快速排序的关键是Partition过程,它对子数组A[p..r]进行就地排序,代码如下:

 1 int Partition(int *A,int p, int r)
 2 {
 3     int i,j,x;
 4     x=A[p];                       //选取第一个元素作为主元
 5     i=p;
 6     for(j=p;j<r;j++)
 7     {
 8         if(x>=A[j+1])              //若小于等于主元则交换元素j+1和i+1
 9         {
10          int temp;
11          temp=A[i+1];
12          A[i+1]=A[j+1];
13          A[j+1]=temp;
14          i++;    
15         }
16     }
17     int temp;                     //最后一步,将主元放到合适的位置,因为此处选取的主元的第一个元素,而i所指向的是最后一个小于等于主元的元素,因此交换主元和i元素,
使得A[p..q-1]的元素都小于等于A[q],A[q+1..r]都大于等于A[q]
18 temp=A[p]; 19 A[p]=A[i]; 20 A[i]=temp; 21 return i; 22 }

下图左边描述了快排的Partition过程,图中主元选取的是最后一个元素跟上述代码不一样,不过这没关系。右边是快速排序的动态演示。

始终记住,i是小于和大于主元的分界线,二j是已处理和未处理的分界线,即i前面的元素都是小于等于主元,而i+1到j都是大于等于主元的元素,j之后的元素是还没比较的元素。

 

 

最后,贴上我在devc++里写的完整代码:

 1 #include <iostream>
 2 #include <stdlib.h>
 3 using namespace std;
 4 
 5 int QuickSort(int *A,int p, int r);
 6 int Partition(int *A,int p, int r);
 7 
 8 int main()
 9 {
10     int i,n;
11     cout<<"Please input the size of your array"<<endl;
12     cin>>n;
13     int *A = new int[n];
14     cout<<"Please input your array"<<endl;
15     for(i=0;i<n;i++)
16     {
17         cin>>A[i];      
18     }
19     QuickSort(A,0,n-1);
20     for(i=0;i<n;i++)
21     {
22         cout<<A[i]<<" ";
23           
24     }
25     cout<<endl;
26     delete A;
27     system("pause");
28     return 0;
29 }
30 
31 int QuickSort(int *A,int p, int r)
32 {
33     if(p<r)
34     {
35         int q;
36         q=Partition(A,p,r);
37         QuickSort(A,p,q-1);
38         QuickSort(A,q+1,r);
39     }
40 }
41 
42 int Partition(int *A,int p, int r)
43 {
44     int i,j,x;
45     x=A[p];
46     i=p;
47     for(j=p;j<r;j++)
48     {
49         if(x>A[j+1])
50         {
51          int temp;
52          temp=A[i+1];
53          A[i+1]=A[j+1];
54          A[j+1]=temp;
55          i++;    
56         }
57     }
58     int temp;
59     temp=A[p];
60     A[p]=A[i];
61     A[i]=temp;
62     return i;
63 }

 另外,快排还有一种典型的实现方法,就是霍尔快排,维基百科上介绍的快速排序就是这种实现。下面贴上维基百科的霍尔快排:

 1 void swap(int *x, int *y) {
 2     int t = *x;
 3     *x = *y;
 4     *y = t;
 5 }
 6 void quick_sort_recursive(int arr[], int start, int end) {
 7     if (start >= end)
 8         return;//這是為了防止宣告堆疊陣列時當機
 9     int mid = arr[end];
10     int left = start, right = end - 1;
11     while (left < right) {
12         while (arr[left] < mid && left < right)
13             left++;
14         while (arr[right] >= mid && left < right)
15             right--;
16         swap(&arr[left], &arr[right]);
17     }
18     if (arr[left] >= arr[end])
19         swap(&arr[left], &arr[end]);
20     else
21         left++;
22     quick_sort_recursive(arr, start, left - 1);
23     quick_sort_recursive(arr, left + 1, end);
24 }
25 void quick_sort(int arr[], int len) {
26     quick_sort_recursive(arr, 0, len - 1);
27 }
View Code

 

转载于:https://www.cnblogs.com/danieldachao/p/5722095.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值