常用排序算法之快速排序

快速排序:

快速排序也是一种分治的递归算法。

  • 快速排序算法基本思想

取数组S中任一元素v,作为枢纽元。用枢纽元将S中的元素分成俩部分,对这两部分分别再次进行快速排序。当S中元素个数是0或1时,则返回。因为快速排序要根据枢纽元将元素分成俩部分,因此,枢纽元的选取对程序的时间复杂度是有影响的。一般的枢纽元选取策略是取左端、右端和中间位置上的三个元素的中值作为枢纽元。

  • 程序实现

#include <iostream>
using namespace std;
typedef int ElementType;
void print(int a[], int n){    
    for(int j= 0; j<n; j++)
    {  
        cout<<a[j] <<" ";  
    }  
    cout<<endl;  
}  
void
Swap( ElementType *Lhs, ElementType *Rhs )
{
    ElementType Tmp = *Lhs;
    *Lhs = *Rhs;
    *Rhs = Tmp;
}
void InsertionSort( ElementType A[ ], int N )
{
    int j, P;
    ElementType Tmp;
    for( P = 1; P < N; P++ )
    {
        Tmp = A[ P ];
        for( j = P; j > 0 && A[ j - 1 ] > Tmp; j-- )
            A[ j ] = A[ j - 1 ];
        A[ j ] = Tmp;
    }
}
ElementType
Median3( ElementType A[ ], int Left, int Right )
{
    int Center = ( Left + Right ) / 2;
    if( A[ Left ] > A[ Center ] )
        Swap( &A[ Left ], &A[ Center ] );
    if( A[ Left ] > A[ Right ] )
        Swap( &A[ Left ], &A[ Right ] );
    if( A[ Center ] > A[ Right ] )
        Swap( &A[ Center ], &A[ Right ] );
    Swap( &A[ Center ], &A[ Right - 1 ] );  /* Hide pivot */
    return A[ Right - 1 ];                /* Return pivot */
}
#define Cutoff ( 3 )//确保有三个元素用于查找枢纽元
void
Qsort( ElementType A[ ], int Left, int Right )
{
    int i, j;
    ElementType Pivot;
    if( Left + Cutoff <= Right )//对于小数组来说,插入排序的效果更好
    {
        Pivot = Median3( A, Left, Right );
        i = Left; j = Right - 1;//i是左端第一个,j是右端第二个元素。最右端位置存放枢纽元。
        for( ; ; )
        {
            while( A[ ++i ] < Pivot ){ }//先将i+1,移过左端第一个,再和枢纽元进行比较,因为在选择枢纽元的时候已经将A[Left]与枢纽元比较过了,而且
            while( A[ --j ] > Pivot ){ }//先将j-1,移过右端第二个,再和枢纽元进行比较,因为在选择枢纽元的时候已经将右端第二个与枢纽元比较过了
            if( i < j )
                Swap( &A[ i ], &A[ j ] );//将i移过小于枢纽元的元素,将j移过大于枢纽元的元素。若i仍然小于j。就交换指针i和j所在的元素。
            else
                break;//否则就结束。
        }
        Swap( &A[ i ], &A[ Right - 1 ] );  //将枢纽元放到左右部分元素交汇处。
        Qsort( A, Left, i - 1 );对左右部分递归调用快速排序
        Qsort( A, i + 1, Right );
    }
    else  /* Do an insertion sort on the subarray */
        InsertionSort( A + Left, Right - Left + 1 );
}
void
Quicksort( ElementType A[ ], int N )
{
    Qsort( A, 0, N - 1 );
}
int main()
{
    int a[10]={8,1,4,9,0,3,5,2,7,6};
    print(a,10);
    Quicksort(a,10);
    print(a,10);
    system("pause");
    return 0;
}

  • 程序实现分析

十个元素:

                                              

 先找出第一个位置、最后一个位置以及中间位置处的元素的中间值[(left+right)/2]向下取整作为枢纽元,找到枢纽元与最后一个位置处的值交换。

                                                                                              

 初始时刻i指向第一个元素,j指向倒数二个元素,最后一个位置存放的是枢纽元。此时,i所指向的元素大于枢纽元,停止。j往前移动指向2,j所指向的元素小于枢纽元,停止。将i和j所指向的值进行交换。

                                              

 i向后移动,直到i指向9,大于枢纽元,停止。j往前移动指向5,j所指向的元素小于枢纽元,停止。将i和j所指向的值进行交换。

                                                                                                

这时,i继续向后移,移过那些小于枢纽元的元素,直到i指向9,大于枢纽元,停止。j向前移移过大于枢纽元的元素,直到j指向3,小于枢纽元,停止。

                                               

此时i>j.i以后的元素全部大于枢纽元,i以前的元素全部小于枢纽元。因此,不再交换。

                                              

这时,整个数组被枢纽元分成俩部分,第一部分:left到i-1位置上的元素均小于枢纽元。第二部分:i+1到right部分的元素均大于枢纽元。分别对这两部分再次进行快速排序。最终得以将数组全部排好序。

简易算法实现:

#include<iostream>
using namespace std;

#define MAX 255

void QuickSort(int *a,int left, int right)
{
	if (left >= right)
		return;
	int mid = a[left];
	int i = left+1;
	int j = right;
	int temp;
	while (1)
	{

		while (a[i] < mid)
			i++;
		while (a[j] > mid)
			j--;
		

		if (i < j)
		{
			temp = a[j];
			a[j] = a[i];
			a[i] = temp;
		}
		else
			break;
	}
	temp = a[left];
	a[left] = a[j];
	a[j] = temp;


	QuickSort(a,left,j-1);
	QuickSort(a, j+1, right);

}

int main()
{
	int a[MAX]; int n=0;
	cout << "请输入需要排序的数的个数:" << endl;
	cin >> n;
	cout << "请依次输入每个数:" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	QuickSort(a,0, n-1);

	cout << "经过排序后的数组为:" << endl;
	for (int i = 0; i < n; i++)
	{
		cout<< a[i]<<"  ";
	}
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值