选择排序及其改进、堆排序

#include <iostream>
#include "iomanip"
using namespace std;
/*
选择排序思想:
每一趟(如第i趟)从后面n-i+1个待排序的元素中选出关键字最小的元素,
作为有序子序列(前i-1个有序)的第i个元素,直至n-1趟结束。
因为最后一个元素是不用再排序的(没有比它再小的元素了,他是最后一个)
*/
void selectSort(int a[] , int n)
{
    int min;//记录最小元素的下标
    for(int i = 1; i <= n ; i++)
    {
        min = i;
        for(int j = i+1 ; j <= n ; j++)
        {
            if(a[j] < a[min])
            {
                min = j;
            }
        }
        swap(a[min],a[i]);
    }
}
/*
选择排序改进的算法思想:
在选择排序每趟选取最大元素的过程中,判断接下来的元素是否有序。
倘若有序则停止。否则,继续。
该算法和先前的选择排序算法差别在于:时间复杂度与初始序列有关。
*/
int _max(int a[] , int n , int &m)
{
    int pos = 0;//确定从a[0:n-1]最大元素的下标
    for(int i = 1 ; i < n ; i++)
    {
        if(a[i] > a[pos])
        {
            pos = i;//记录最大元素的位置
            m++;
            //记录递增的正序对的个数。如 1 2 3 4那么该判断语句就会记录m=4
            //那么如果m等于p-1,即p之前的元素都有序则结束。
        }
    }
    return pos;
}
void selectSortModify(int a[] , int n)
{
    int m = 0;//正序对个数,如果a[1]-a[i]是正序那么m会在max函数中记录a1到ai的个数。
    for(int p = n ; p > 1 ; p--)
    {
        int j = _max(a , p , m);
        swap(a[p-1] , a[j]);//因为p是从n开始,而数组下标是1到(n-1)
        if(m == p-1) break;
    }
}



/*
堆排序思想:
1、建堆 2、进行堆排序输出。而这两个部分都要借助堆的调整(因为每次输出元素会影响树)
*/

void headAdjust(int a[] , int k , int n)
{
    a[0] = a[k];
    for(int i = 2*k ; i <= n ; i*= 2)
    {
        if(i < n && a[i] < a[i+1])
        {//i<n保证k有左右孩子节点;
        //a[i] < a[i+1]保证i所指为子节点最大值。
            i++;
        }
        if(a[0] >= a[i]) break;//满足大根堆的要求
        else
        {
            a[k] = a[i];//把i(k的最大子节点)换到k的位置,保证k大于子节点值。
            k = i;
            //修改调整的元素,因为此时是a[k](最初的k)换在了i的位置上,
            //而且该位置还不一定是最终位置,
            //还要继续判断其和孩子节点是否满足大根堆的要求。
        }
    }
    a[k] = a[0];//找到最初k的最终位置。
}

void BuildHeap(int a[] , int n)//对下标1-(n-1)个元素进行构建堆
{//根据完全二叉树性质n/2为分支节点
    for(int i = n/2 ; i > 0 ; i--)
    {//从n/2到1,反复调整堆。因为在所选的元素进行调整后,可能会对其继续调整。
    //比如i=n/2对其孩子调整完后,n/2的父节点比它还小
    //(因为此时表是无序的,所以可能发生)
    //那么其父节点就要往下调整,来保证大根堆,n/2的节点可能往上调。
        headAdjust(a , i , n);
    }
}

void HeapSort(int a[], int n)
{
    BuildHeap(a,n);
    for(int i = n ; i > 1 ; i--)
    {
        swap(a[i] , a[1]);//第一个元素和最后一个元素互换
        headAdjust(a , 1 , i-1);
    }
}



int main()
{
    int a[10] = {1,9,2,0,12,4,5,3,7,10};
    selectSortModify(a , 10);
    for(int i = 0 ; i < 10 ; i++)
        printf("%d ",a[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

让我试试哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值