选择排序--简单选择排序、堆排序

选择排序是一种简单但却效率低的算法,基本思想是:从待排序数组中选择最小(或最大)元素,将其放置在数组的起始位置,然后再从剩余的未排序部分中选择出最小(或最大)元素放置到已排序部分的末尾,直到数组中所有元素都有序为止。

1.简单选择排序

基本思想是:每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止。

说白了就是,一个序列,把第一个元素设为最小min,然后从其后面的元素开始搜索比min小且最小的元素,将其替换;再min+1,即后移一位,再进行比较,直到min=n-1为止,完成排序。

typedef int Elemtype;
void SelectSort(Elemtype arr[],int n)
{
    for(int i=0;i<n-1;i++)
    {
        int min=i;
        for(int j=i+1;j<n;j++)//搜索小于min的最小元素 
        {
            if(arr[min]<arr[j])//找到比min晓得元素就将min指向这个元素 
                min=j;
        }
        if(min!=i)
            swap(arr[i],arr[min]);
    }
}

空间效率:空间复杂度为O(1)。

时间效率:时间复杂度为O(n^2)。

2.堆排序

堆排序说白了就是,将一个待排序的数组看作一个完全二叉树,采用大根堆的形式构造这个二叉树,此时根节点就是整个数组的最大值,然后将最大值与最后一个值交换(此时的最大值不再参与排序),交换后堆的排序混乱,重新构建堆;然后将此时的根节点也后移(但在前一个最大值之前),再重新构建堆;重复至堆只剩一个元素,完成排序。

基本思路:

  1. 将待排序的序列构建成一个大根堆或小根堆。

  1. 将堆顶元素与堆底元素交换。

  1. 对剩余的元素重新构建堆。

  1. 重复步骤2和3,直到整个序列有序。

void Adjust(int *arr,int i,int length) //调整一个堆,形成大根堆
{    
    int left=2*i+1; //左子节点下标
    int right=2*i+2; //右子节点下标
    int max=i; //初始化,假设左右孩子的父节点就是最大值 
    
    if(left<length && arr[left]>arr[max]) //左子节点比最大节点大
        max=left;
    if(right<length && arr[right]>arr[max]) //右子节点比最大节点大
        max=right;
    if(max!=i)
    {   //若最大值max已经发生变化,则交换值,把最大的值放到根节点 
        swap(arr[max],arr[i]);
        Adjust(arr,max,length);    //递归,使其子树也为堆 
    }
}
void HeapSort(int *arr,int length) //堆排序
{    
    for(int i=length/2-1;i>=0;i--) //从最后一个非叶子节点开始向上遍历,建立大根堆 
        Adjust(arr,i,length);

    for(int j=length-1;j>0;j--) //调整序列,注意此时要将堆看成序列 
    {          
        swap(arr[0],arr[j]); //将第一个值与最后的值交换,就是将最大值移到后面 
        Adjust(arr,0,j); //因为每交换一次之后,就把最大值拿出(不再参与调整堆),第三个参数应该写j而不是length  
    }
}

空间效率:空间复杂度为O(1)。

时间效率:时间复杂度为O(Nlog2N)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值