您的位置:首页 > 编程语言 > C语言/C++

比较排序之堆排序和快速排序

2016-09-17 22:24 211 查看

堆排序

堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个结点对应数组中的一个元素。除了最底层外,改树是完全充满的,而且是从左往右填充的。
堆可以分成两种形式:最大堆和最小堆。
在堆排序算法中,我们使用的是最大堆。最小堆一般用于构建优先队列。
我们知道,在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足:
A[parent(i)]>=A[i]
也就是说,某个结点的值至多与其父节点一样大,因此,堆中最大的元素存放在根结点中。
所有我们需要一个用于维护最大堆性质的函数。它的输入是一个数组A和一个下标i,我们维护最大堆性质函数的作用就是让以下标i为根结点的堆遵循最大堆性质。


void max_heap(int *a,int i,int n)      //n=a.length
{
int j=i*2+1;          //i's child node
int temp=a[i];
while(j<n)
{
if(a[j]<a[j+1]&&j+1<n)
j++;
if(a[i]>=a[j])
break;
a[i]=a[j];
i=j;
j=i*2+1;
}
a[i]=temp;
}


现在我们就可以将我们要排序的数据建成一个最大堆数组。


void build_max_heap(int *a,int n)
{
for(int i=n/2-1;i>=0;i--)
max_heap(a,i,n);
}


现在我们拥有了建立最大堆的能力,那么我们就可以用它来排序,因为最大的元素就在根结点处,所以我们将根结点放入数组的最后,然后将剩下的元素再建成一个最大堆,再将根结点放入数组的最后,依次循环,我们就排好序了。


void heap_sort(int *a,int n)
{
for(int i=n-1;i>=0;i--)
{
build_max_heap(a,i+1);
swap(a[0],a[i]);
}
}


我们可以看出堆排序的时间复杂度跟归并排序相同是O(nlgn),但是它的空间复杂度与插入排序相同都是常数。


快速排序

快速排序也使用了分治思想,它的原理是找一个主元,然后将数组里的每一个元素与主元相比较,比主元小的放在主元左边,比主元大的放在主元右边,然后以主元为界,对左右两个子数组进行相同的操作,依次下去,就可以排好序了。
下面我们以数组最后一个元素为主元:


int partition(int *a,int i,int n)
{
int key=a
;
int m=i-1;
for(int j=i;j<n;j++)
{
if(a[j]<=key)
{
m+=1;
swap(a[m],a[j]);
}
}
swap(a[m+1],a
);
return m+1;
}

void quick_sort(int *a,int i,int n)
{
int q;
if(i<n)
{
q=partition(a,i,n);
quick_sort(a,i,q-1);
quick_sort(a,q+1,n);
}
}


我们可以看到快排的最坏情况时间复杂度是O(n^2),而在元素互异的情况下,期望时间复杂度是O(nlgn)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐