选择排序之简单选择排序与堆排序

在数据结构里面,选择排序又简单的分为简单选择排序及堆排序,都为不稳定排序

一、简单选择排序

在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换(这里采用最小值);然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

简单选择排序的实现
#define MAXSIZE 20  //默认定义数据大小为20
#define T int

typedef T Seqlist[MAXSIZE];

void swap(T *a,T *b)
{
    T temp = *a;
    *a = *b;
    *b = temp;
}

int Select_min_pos(Seqlist &L,int k,int n)//确定最小值的位置确定
{
    T min_val = L[k];
    int pos = k;
    for(int i=k+1;i<n;++i)
    {
        if(L[i] < min_val)
        {
            min_val = L[i];
            pos = i;
        }
    }
    return pos;
}

void Select_sort(Seqlist &L,int n)   //选择排序
{
    for(int i = 0;i<n-1;++i)
    {
        int j = Select_min_pos(L,i,n);
        if(j != i)
        {
            swap(&L[j],&L[i]);
        }
    }
}

二、堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。

堆的定义如下:具有n个元素的序列(k1,k2,…,kn),当且仅当满足这里写图片描述

时称之为堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最小项(小顶堆)。
若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如:
(a)大顶堆序列:(96, 83,27,38,11,09)
(b) 小顶堆序列:(12,36,24,85,47,30,53,91)
这里写图片描述

初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序。

堆排序的实现

#define MAXSIZE 20  //默认定义数据大小为20
#define T int

typedef T Seqlist[MAXSIZE];

void swap(T *a,T *b)
{
    T temp = *a;
    *a = *b;
    *b = temp;
}
void siftdown(T heap[],int n,int p)//向下调整
{
    int i = p;//小堆结构里的父节点
    int j = 2*i + 1;//小堆的左子树
    while(j<n)
    {
        if(j<n-1 &&heap[j]>heap[j+1])
            j++;          //保证j指向子树里面的较小值
        if(heap[i]<=heap[j])
            break;
        else
        {
            swap(&heap[i],&heap[j]);//如果小堆结构里面父节点大于子树,交换它俩的值
            i = j;
            j = 2*i+1;
        }
    }
}

T remove_min_key(T heap[],int n)
{
    T key = heap[0];
    heap[0] = heap[n];
    siftdown(heap,n,0);//重新向下调整
    return key;
}
void Heap_sort(Seqlist &L,int n)    
{
    T *heap = (T*)malloc(sizeof(T) * n);
    assert(heap != NULL);
    int i;
    for( i = 0;i<n;++i)
    {
        heap[i] = L[i];
    }
    int curpos = n/2 -1;//最底层小堆结构
    while(curpos >= 0)
    {
        siftdown(heap,n,curpos);
        curpos--;
    }
    for(i = 0;i<n;++i)
    {
        L[i] = remove_min_key(heap,n-i-1);  //每次去掉小堆结构的最顶端,即最小值
    }
    free(heap);
    heap=NULL;
}

堆排序测试文件

void main() {
    Seqlist L = {16,33,9,8,25,21,3,49,5};
    int n = 9;
    Heap_sort(L,n);
    for(int i = 0;i < n;++i)  
    {
        cout<<L[i]<<"  ";
    }
}

建堆时的比较次数不超过4n 次,因此堆排序最坏情况下,时间复杂度也为:O(nlogn )。堆排序是一种不稳定排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值