堆排序
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
以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章