名称:选择排序---简单选择排序和堆排序

/*
名称:选择排序—简单选择排序和堆排序
说明:
对于简单选择排序来说,其主要的算法思想是每次从后面没确定的自序列中选取一个最小的(如果是从小到大排序)元素,与当前元素进行交换。其基本的算法时间复杂度为:O(N2)。对于这个算法来说,其比较次数与初始的序列状态没关系,无论如何,都需要进行n(n-2)/2次比较。由于其在确定元素位置的时候用到了交换,这就造成了对于相同关键字的元素,交换之后前后顺序可能发生变化。因此,这是一个不稳定的排序算法。
对于堆排序来说,虽然其逻辑是二叉树的结构,但是其存储的物理结构确确实实是一个顺序数组。(这应该算是一个理解逻辑结构和存储结构区别的好例子了)。其算法思想是:把一列元素看成一个堆,一个父亲结点大于子结点的堆(和二叉排序树不一样),这样你会发现,在这列元素中已经包含了某种特定关系的自序列。而这个关系就是父结点大于子结点,这样在每次排序时,就不用搜索所有元素,只要对特定的元素进行排序即可,即调整序列依然成为堆。在我看来,这应该是堆排序能大大降低时间复杂度的原因。其最终的时间复杂度为O(nlog2n)。还有由于它也是基于交换的,所以它也是一个不稳定的算法。还要补充一点的是,对堆的操作涉及到初始化建堆和对堆进行调整。

*/

#include<iostream>
using namespace std;

//简单选择排序
void SelectSort(int elem[],int n)
{
    int _min = 0,temp = 0;
    for(int i = 0;i<n-1;++i)
    {
        _min = i;

        for(int j = i+1;j < n;++j)
            if(elem[j] < elem[_min])      //选择最小的元素
                _min = j;

        if(i != _min)       //如果不和原来的位置相等,则进行交换
        {
            temp = elem[i];
            elem[i] = elem[_min];
            elem[_min] = temp;

        }

    }
}


//向下调整
void AdjustDown(int elem[],int pos,int len)
{
    elem[0] = elem[pos];        //elem[0]  暂存

    for(int i = pos*2;i <= len; i*=2)       //向下筛选
    {

        if(i < len && elem[i]<elem[i+1])        //取key值较大的子结点的下标
            ++i;

        if(elem[0] >= elem[i])      //筛选结束
            break;
        else
        {
            elem[pos] = elem[i];        //将elem[i]调整到双亲节点
            pos = i;                //修改k值,以便继续向下筛选
        }
    }

    elem[pos] = elem[0];            //被筛选结点的值放入最终的位置
}

//初始化建立大根堆
void BuildMaxHeap(int elem[],int len)
{
    for(int i = len/2;i>0;--i)
        AdjustDown(elem,i,len);
}



//堆排序
void HeapSort(int elem[],int len)
{
    int t = 0;
    BuildMaxHeap(elem,len);     //初始化建立大根堆

    for(int i = len;i>1;--i)
    {
        cout<<elem[1]<<" ";

        t = elem[1];
        elem[1] = elem[i];
        elem[i] = t;


        AdjustDown(elem,1,i-1);         //向下调整,保持堆的结构
    }
}

总结:写了几个经典的排序算法后,隐隐的有点感觉,有很多改进的排序算法都是利用已知序列间的部分有序自序列,或者自序列中含有某种特定关系的。当然这种自序列可能一开始并不存在,需要自己去创造。比如说堆排序、shell排序。其实总某种角度上说,快速排序也算是,因为其每次选取基准后,就把原序列分成了两个自序列,使得下一次排序时只要在自序列中进行就可以了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值