快速排序算法

快速排序是基于分治模式的。

一.基本思路:

1.找出一个基准数;

2.重新排列数列,把比基准数小的放在前面,比基准数大的放在后面,分割结束后,基准数就是中间数,此操作也成为分割操作;

3.递归的把被基准数分开的两个序列重新排序。

快速排序是递归思想的经典运用。

该算法是由东尼·卡尔先生在1962年提出来的。

二.分解方法:

数组A[p…r]被划分成两个可能空的子数组A[p..q-1]<=A[q]<=A[q+1..r].

三.解决方法:
通过递归调用进行快速排序。

四.合并:

因为两个子数组是就地排序的,所以他们的合并不需要进行操作。

五.伪代码:

版本一:

因为选择排序算法有很多种版本,此处首先选择《算法导论》中的所用的那一版,即使用数组的最后一个元素作为主元进行排序

QUICKSORT(A,p,r)
 If(p<r)
   Then q←PARTION(A,p,r)
              QUICKSORT(A,p,q-1)
              QUICKSORT(A,q+1,r)
 
PARTION(A,p,r)
x←A[r]
i←p-1
forj←p to r-1
   do if A[j]<=x
      then i←i+1
         exchange A[i]A[j]
exchange A[i+1]A[r]
return i+1

六.源代码实现:

#include<stdio.h>
#include<stdlib.h>
#define MAX 8
 
void exchange(int *x,int *y)//此处必须用指针实现,否则由于函数的拷贝不能改变调用函数的参数值
{
         int temp;
         temp=*x;
         *x=*y;
         *y=temp;
}
 
int partion(int v[],int p,int r)
{
         int x=v[r];
         int i=p-1;
         int j;
         for(j=p;j<=r-1;j++)
         {
                   if(v[j]<x)
                   {
                            i++;
                            exchange(&v[i],&v[j]);
                   }
         }
         exchange(&v[i+1],&v[r]);
         return i+1;
}
void QuickSort(int v[],int p,int r)
 {
         int q=0;
         if(p<r)
         {
             q=partion(v,p,r);
             QuickSort(v,p,q-1);
             QuickSort(v,q+1,r);
         }
 
}
 
int main()
{
         int v[MAX];
         for(int i=0;i<MAX;i++)
             scanf("%d",&v[i]);
 
         QuickSort(v,0,MAX-1);
 
         for(int j=0;j<MAX;j++)
                   printf("%d\t",v[j]);
         system("pause");
         return 0;
}


七.运行结果:

wKioL1P7Ng6ii3iiAABwMgHngCY650.png

八.算法演示:

wKioL1P7NrzAtAE2AALviB5DjVs271.jpgwKiom1P7NdOjZqWQAALYCxPV-FA293.jpg

附:

版本二:

把数组的第一个元素作为主元进行排序


伪代码:

QUICKSORT

i←p

j←r

x←v[p]

if p<r

 while i<j

    while v[j]>=x

        j--    //从右边向左边数找到第一个比主元小的数

    if i<j

        v[i]=v[j] //把找到的数赋给左边被“挖掉的”数

          i++

    while v[i]<x

          i++     //从左边向右边找,找到第一个比主元大的数

    if i<j

        v[j]=v[i] //再把找到的数赋给右边“被挖掉的”数

          j--


x←v[i]

 QUICKSORT //再递归

 

源代码实现:

#include<stdio.h>
#include<stdlib.h>
#define MAX 8

void QuickSort(int v[],int p,int r)
 {
	if (p<r)
	{
		int x=v[p];
		int i=p;
		int j=r;
		while(i<j)
		{
			while(v[j]>=x&&i<j)
				j--;
			if(i<j)
				v[i++]=v[j];
				

			while(i<j&&v[i]<x)
				i++;
			if(i<j)
				v[j--]=v[i];
		}
		v[i]=x;
		QuickSort(v,p,i-1);
		QuickSort(v,i+1,r);
	}
}

int main()
{
	int v[MAX];
	for(int i=0;i<MAX;i++)
		scanf("%d",&v[i]);

	QuickSort(v,0,MAX-1);

	for(int j=0;j<MAX;j++)
		printf("%d\t",v[j]);
	system("pause");
	return 0;
}

运行结果

    wKioL1P7Ng6ii3iiAABwMgHngCY650.png

算法演示:

wKiom1P74-DwFMbFAAc2tPYoOHY638.png

       从上图可以看出最终此数列被2分为两个子数列,然后以此类推进行递归排序,请读者自己进行后面的步骤


九.总结:


关于快速排序的版本还有很多,但无非是选择主元的方式和位置不同罢了,这里只选择两个典型的方法进行初步介绍,至于算法性能等进阶的问题,会在后面继续进行详细介绍。


版本一和版本二,理解任意一种即可,但个人认为第二种似乎比较容易理解,且代码也简洁明了,值得学习。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章