被问了好多次的基本排序算法,好多次都支支吾吾的说不出个所以然。这次下定决心好好总结下,并记录在此以免忘记
一:快速排序
定义以及算法方法参加百科http://baike.baidu.com/view/19016.htm
快排就是把要进行排序的序列(数组)分为两部分,用枢纽元隔开(就是分隔的用的元素)。前面的一部分都比枢纽元小(或者大),后面一部分都比枢纽元大(或者小)
逐级递归划分直到排序完成。
假设一个数组a[0]..........a[n].从中随机取一个元素作为枢纽元 a[i] (i = rand() % n).再对数组进行划分,划分为为a[i]小和a[i]大的两部分,再对此两部分分别
进行划分,以此类推直到划分完毕为止.
直接上代码:
int partition(int nAry[],int nBegin, int nEnd)
{
srand(int(time(0)));//随机种子
int nPivod = nBegin + rand() % (nEnd - nBegin);
//把枢纽元放到首元素位置
swap(nAry,nBegin, nPivod);
//两个标记,nFrontFlag标记比nAry[nPivoid]大的元素位置
//nBlackFlag往后寻找,直到找到比nAry[nPivoid]小的元素就和nFrontFlag位置的元素交换
//nFrontFlag再往后移动一个位置,此位置它所在的元素就大于nAry[nPivoid]
//因为nBlackFlag之前的位置都是比nAry[nPivoid]要大的元素
int nFrontFlag = nBegin + 1;
int nBlackFlag = nBegin + 1;
for(nBlackFlag; nBlackFlag <= nEnd; nBlackFlag++)
{
if(nAry[nBlackFlag] < nAry[nBegin])
{
if(nBlackFlag != nFrontFlag)
swap(nAry, nBlackFlag, nFrontFlag);
nFrontFlag++;
}
}
//把枢纽元素放到枢纽位置。nFrontFlag位置就是枢纽位置
swap(nAry, nBegin, nFrontFlag - 1);
return nFrontFlag - 1;
}
void quicksort(int nAry[], int nBegin, int nEnd)
{
if(nBegin >= nEnd)
return;
int nPartion = partition(nAry, nBegin, nEnd);
quicksort(nAry, nBegin, nPartion);
quicksort(nAry, nPartion + 1, nEnd);
}
当然最好的枢纽元素还是取中值,就是首元素、尾元素、中间元素取中值。
二:堆排序
选择法排序就是从数组中选择最大、第二大、第三大。。这样的数一次和数组的前面元素进行交换。在选择最大、次大的元素过程中经历了很多重复的比较,这样效率就有所降低
堆排序就是构造一个堆结构,这个结构的首元素最大(或者最小)。在堆结构中进行比较的次数就会大幅减少
堆结构就是一个序列a[0]....a[n].序列中a[2 * i + 1]、a[2 * i + 2]必须>=a[i](或者<=).放到树结构中就是叶子节点必须大于等于其孩子节点
代码:
//从nBegin节点开始更新其孩子节点,让其符号堆结构
void UpdateHeap(int nAry[], int nBegin, int nLen)
{
while((2 * nBegin + 1) < (nLen - 1))
{
int nLeft = 2 * nBegin + 1;
int nRight = 2 * nBegin + 2;
if(nRight < (nLen - 1))
{
if(nAry[nRight] > nAry[nLeft])
nLeft = nRight;
}
if(nAry[nBegin] < nAry[nLeft])
{
swap(nAry, nBegin, nLeft);
nBegin = nLeft;
}
//后面的已经处理过了
else
break;
}
}
//建立堆结构,从中间元素开始。叶子节点是堆结构,其孩子节点也是堆结构
void BulidHeap(int nAry[], int nLen)
{
for(int i = (nLen / 2); i >= 0; i--)
{
UpdateHeap(nAry, i, nLen);
}
}
void heapsort(int nAry[], int nLenAry)
{
BulidHeap(nAry, nLenAry);
//首元素为堆顶元素。后面元素为已经排好序的
for(int nLen = nLenAry; nLen > 0; nLen--)
{
if(nAry[0] > nAry[nLen - 1])
{
swap(nAry, 0, nLen - 1);
UpdateHeap(nAry, 0, nLen);
}
}
}
应用:Top K问题
题目描述:5.查找最大的k个元素
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最大的4个数字为5,6,7,8
这样的题目要求一般是n比大数量级的,直接对其进行排序,再取K个元素就难免有SB了。
浙公网安备 33010602011771号