快速排序:
快速排序也是一种分治的递归算法。
- 快速排序算法基本思想:
取数组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]<<" ";
}
}