《算法导论》读书笔记--快速排序

快速排序是最坏情况时间复杂度为O(n²),最优时间复杂度为O(nlgn),平均时间复杂度为O(nlgn)。

最坏情况出现在每一层划分子问题时,分别包含了n-1个元素和0个元素,此时的时间复杂度为O(n²),与插入排序相同;在数组已经有序时其时间复杂度依旧为O(n²),此时插入排序的时间复杂度为O(n)。


快速排序使用了分治思想,将数组A[p..r]划分为两个子数组A[p..q-1]和A[q+1..r],使A[p..q-1]中的元素都小于A[q],A[q+1..r]中的元素都大于A[q],不断进行递归这个过程,直到数组中只存在一个元素,此时,数组已经有序。

QUICKSORT(A,p,r)
if p < r //当数组中只剩一个元素时,退出递归,数组已经有序
    q = PARTITION(A,p,r)
    QUICKSORT(A,p,q-1) //对小于等于A[q]的元素进行递归
    QUICKSORT(A,q+1,r) //对大于A[q]的元素进行递归


划分数组:

PARTITION(A,p,r)
    x = A[r] //将A[r]选取为“主元”
    i = p - 1 //因为可能不存在小于等于A[r]的元素,所以i的值由p-1开始
    for j = p to r-1 
        if A[j] <= x 
            i = i + 1 //小于等于x的元素增加一个
            exchange A[i] with A[j] //i+1后,i指向了一个大于x的元素,此时,j指向的是一个小于等于x的元素,交换这两个元素的位置,使其符合规则
    exchange A[i+1] with A[r] //r前所有元素比较完后,将A[r]置于正确位置:两个子数组的交界处
    return i + 1 //返回"主元"的位置

在整个for循环过程中,数组被划分为了四个区域:

1.小于等于A[r],元素位于[p,i]                     

2.大于等于A[r],元素位于(i,j)

3.未划分区域 [j,r)

4.主元 [r,r]

Demo:

#include 
#include 
using namespace std;

void swap(int *a,int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

int partition(int *A,int p,int r)
{
	int i = p - 1;
	int x = A[r];
	for(int j = p;j < r;j++)
	{
		if(A[j] <= x)
		{
			i++;
			swap(A[j],A[i]);
		}
	}
	swap(A[r],A[i+1]);
	return (i + 1);
}

void quicksort(int *A,int p,int r)
{
	if( p < r )
	{
		int q = partition(A,p,r);
		quicksort(A,p,q-1);
		quicksort(A,q+1,r);
	}
}

int main()
{
	int A[10];
	for(int i = 0;i < 10;i++)
		cin>>A[i];
	quicksort(A,0,9);
	for(int i = 0;i < 10;i++)
		cout << A[i] <<" ";
	getchar();
	system("pause");
	return 0;
}


你可能感兴趣的:(算法)