堆排序

Posted kjkj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。

堆是一个完全二叉树(对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树),常用来利用树的性质进行排序,即堆排序。

排序过程

0.输入一个集合R[0,n],先把该集合元素构成树(分层,第一个元素在第一层,依次按完全二叉树性质放置其余元素)

1.把树调整为大顶堆或小顶堆;

2.将R[0]和R[n]互换位置(即将最大的或最小的元素放到最后位置),此时将原集合分为两个集合:R[0,n-1]与R[n](即无序区与有序区)

3.待交换数据结束,剩下元素可能不满足堆性质,则将R[0,n-1]集合重新调整位置,将R[0]和R[n-1]位置互换(R[n-1]到了有序区),不断重复该过程,直到有序区元素个数为n-1个,排序结束。

c++代码

#include<iostream>

using namespace std;

//调整方法,构成大顶堆

//array:待调整的集合

//start:最后一个非叶子节点

//end:元素个数(最后位置)

void Adjust(int *array,int start,int end){

  int temp=array[start];

  int i=2*start+1;//左孩子下标,右孩子2*start+2

  while(i<=end){

  //进行交换

  //在孩子中找最大

    if (i+1<=end && array[i+1]>array[i]){

    i++;//右孩子位置

    }

    if(array[i]<=temp){//孩子小于等于爸爸,不需要操作

    break;

    }

    array[start]=array[i];//不交换,直接赋值,直到最后找到最大的才交换,即本循环结束交换:array[start]=temp

    start=i;

    i=2*start+1;//继续查找有没有左孩子

  }

  array[start]=temp;

}

 

//大顶堆

void Sort(int *array,int size){

//本循环执行结束后得到第一个最大值

  for(int i=size/2-1;i>=0;i--){//从最后一个非叶子节点开始,往上到根节点,即从下到上调整

//调整方法,构成相应的大顶堆

     Adjust(array,i,size-1);

  }

//调整结束后交换元素(第一个与最后一个元素交换位置)(相当于一次完整调整树结构后得到顶为最大元素(只能保证顶为最大,其他元素不一定满足大顶堆的性质),然后与目前的最后一个元素交换,之后再对堆结构微调)

for(int j=size-1;j>0;j--){

  int temp=array[j]

  array[j]=array[0]

  array[0]=temp

//交换后可能不满足堆性质,重新调整剩余元素(即第0个元素到倒数第二个元素),即除第一个最大元素之外其他排序结果都是在本循环中得到

  Adjust(array,0,j-1);//第0个元素到倒数第二个元素调整,从上到下调整,每次元素个数减1:j-1

}

}

int main(int argc,const char *argv[]){

  int array[6]={23,43,5,67,87,45};

  Sort(array,6)

  for (int i=0;i<6;i++){

  cout<<array[i]<<",";

}

  cout<<endl;

  return 0;

}

python 代码:

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
           # write code here
                size=len(tinput)
                if size==0 or k>size:#注意k是个数,不是第k个,所以是or k>size-1
                    return []
                array=self.sort(tinput,size)
                return array[:k]
    def sort(self,array,size):
        for i in range(size/2-1,-1,-1):#从第一个非叶子节点到根节点,range取不到最后边的元素所以是-1
            array1=self.adjust(array,i,size-1)
        for j in range(size-1,-1,-1):
            temp=array1[j]
            array[j]=array1[0]
            array1[0]=temp
            array1=self.adjust(array1,0,j-1)#每次元素个数减1
        return array1
    def adjust(self,array,start,end):
        temp=array[start]
        i=start*2+1
        while i<=end:
            if i+1<=end and array[i+1]>array[i]:
                i+=1
            if array[i]<temp:
                break
            array[start]=array[i]
            start=i#往下面一层非叶节点进行判断
            i=start*2+1
        array[start]=temp#所有层级找完后将要判断的temp与目前最大值交换!!!!!!!!!!!这步要注意,temp记录了此次循环的非叶节点的值,array[start]为目前被最大值覆盖了的节点
        return array
           
































以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章

排序算法:堆排序-Java实现

排序算法总结之堆排序

[ 数据结构 -- 手撕排序算法第七篇 ] 堆及其堆排序

重温基础算法内部排序之堆排序法

重温基础算法内部排序之堆排序法

堆(利用堆进行数组排序)-堆排序