快排和堆排序分析

快排最好时间复杂度为(nlog(n)),平均时间复杂度为(nlog(n)),最差时间复杂度(n*n),空间复杂度(log(n))
堆排序最差时间复杂度(nlog(n))


堆的定义:
每一个父亲节点的值都小于2个孩子节点的值,数组排序时,首先将n个数构造一个堆,此时根节点的值一定是最小的。将根节点的值和最后一个节点交换,然后重新移动根节点,得到一个新的根节点,该根节点的值是前n-1个节点中值最小的了,然后再将根节点与第n-1个节点交换,一直重复该步骤,最后得到的数字为逆序数组。


快速排序
每次将左边界的值选出来为a[left],将左边界到右边界的值排序,定义2个标识i,j,   i从左到右直到遇到一个不比a[left]小的值,j从右到左,直到遇到一个不比a[left]大的值,交换a[i]和a[j]的值。直到i>j,将a[left]和a[j]交换, 完成一趟排序,此时j边的都比a[j]小,j右边的都比a[j]大,再排序(left,j-1)和(j+1,right),最好的时候每次将数组平分,这样需要平分log(2,n)次,每次执行的循环都为n次,画一颗二叉树就明白了。。




#include <iostream>
using namespace std;




int a[10005];
int b[10005];
int c[1005];
const int MAXN = 1000000000;
int cnt_qort;
int cnt_heap;


//随机序列
void getRandom()
{
for(int i = 0;i<1001;i++)
{
a[i] = rand()%MAXN;
b[i] = a[i];
c[i] = a[i];
}
}




void qsort(int left,int right)
{
if(left >= right)
return;




//交换位置,使待排序的序列更加随机
int index = rand()%(right-left)+left;
int temp = a[left];
a[left] = a[index];
a[index] = temp;




int i = left,j = right+1;
while (1)
{
do 
{
i++;
cnt_qort++;
} while (i<=right&&a[i]<a[left]);
do 
{
j--;
cnt_qort++;
} while (j>=left&&a[j]>a[left]);
if(i>j)
{
break;
}
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
    temp = a[left];
a[left] = a[j];
a[j] = temp;
qsort(left,j-1);
qsort(j+1,right);
}




/*插入位置n并形成堆*/
void shiftUp(int n)
{
int i = n;
while(1)
{
cnt_heap++;
if(i==1)
break;
int p = i/2;
if(b[i]>=b[p])
break;
int temp = b[i];
b[i] = b[p];
b[p] = temp;
i = p;
}
}




/*位置1的值改变后,向下移动,重新形成堆,保证第一个位置上的数为所有数中最小的*/
void shiftDown(int n)
{
int i = 1;
while(1)
{
cnt_heap++;
int p = 2*i;
if(p>n)
break;
if(p+1<=n&&b[p+1]<b[p])
p++;
if(b[i]<=b[p])
break;
int temp = b[i];
b[i] = b[p];
b[p] = temp;
i = p;
}
}




//排序后为逆序
void heap_sort(int n)
{
int i;
//构建堆
for(i = 2;i<=n;i++)
{
shiftUp(i);
}
for(i = n;i>=2;i--)
{
//1的位置的值总是最小
int temp = b[1];
b[1] = b[i];
b[i] = temp;
shiftDown(i-1);
}
}




void main()
{
getRandom();
heap_sort(10000);
qsort(0,10000);
//快排执行的循环的次数
cout<<cnt_qort<<endl;
//堆排序执行的循环的次数
cout<<cnt_heap<<endl;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值