幸运28源码-出售堆数据结构与堆排序

堆数据结构 幸运28源码-出售Q2152876294 论坛:diguaym.com

堆(二叉堆)是近似的完全二叉树,最底层允许不满,

堆的相关,数组长度length,heap_size有效长度(堆的有效元素,未排序的数目)。Heap_size<length

堆虽然很像二叉树,但是我的理解就是用二叉树的逻辑,但是最主要的区别在,堆的存储是用数组,只是用下标来帮助理解

堆的存储结构

从上往下,按顺序存储。

然后是几个相关的操作,

1、取父节点,取左子节点,取右子节点

2、然后是把数据变成最大堆的操作,其实是从某个节点向下变成最大堆的结构。这个功能完成。

MaxHeap()//时间复杂度是O(logn)

3.建堆的过程又要涉及到length与heap_Size,我的理解是length是数组大小,heap-size是有效数目,在后面堆排序的过程中,可以用来表示未排序的剩余的数目。

有n个有效元素的堆(完全二叉树),叶子节点是n/2+1,到n

用该定理,从最小索引的叶子节点左边开始(第一个非叶子节点,例如上图第五个元素7),递归MaxHeap过程,就建了最大堆。

BuildMaxHeap() 时间复杂度是O(n)

堆排序。

堆结构的根节点是最大数,然后把数组最后一个元素(底层的最后一个叶子节点)与根节点交换,然后再把这个新的根节点(先前的底层的最后一个叶子节点)进行MaxHeap变成最大堆,同时size-1,因为Maxheap会需要用到size判断对不对其进行处理。直到剩下两个元素进行一次交换就可以了。

//堆数据结构与堆排序
#include <iostream>

#define Depth 4//数的深度
#define Size 10

using namespace std;
inline int Parent(int i)//返回父节点的坐标索引,数组都是索引从0开始,
{
return (i+1)/2-1;
}

inline int Left(int i)//返回左子节点的坐标索引,数组都是索引从0开始,
{
return 2*(i+1)-1;
}

inline int Right(int i)//返回右子节点的坐标索引,数组都是索引从0开始,
{
return 2*(i+1);
}
void Swap(int & a,int & b);

void MaxHeap(int a[],int i,int size,int n);//同样i是从0开始的索引,维护i节点向下的最大堆性质,size是有效数据,即前面说的heap_size,n是数组总大小
void BuildMaxHeap(int a[],int size,int n);
void HeapSort(int a[],int n);
int main()
{
int n = 10;
int a[10] = {4,16,10,14,7,9,3,2,8,1};

HeapSort(a,n);

for(int i=0;i<n;i++)
    cout<<"i="<<i<<"a[i]="<<a[i]<<endl;

}

void MaxHeap(int a[],int i,int size,int n)//a 4 10 10
{
int l = Left(i);//9
int r = Right(i);//10
int largest = i;//4
if(l<size && a[l]>a[i])//这里size是数目,第一次是n,而l,r是索引,所以比较的 边界是size-1
largest = l;
if(r<size && a[r]>a[largest])
largest = r;
cout<<"heap i="<<i<<"size="<<size<<"largest="<<largest<<endl;
if(largest!=i)
{
Swap(a[i],a[largest]);
MaxHeap(a,largest,size,n);
}
return;
}

void BuildMaxHeap(int a[],int size,int n)
{
size = n;//这步假设全都没排序,然后用于调用MaxHeap
for(int i=n/2-1;i>=0;i--)
MaxHeap(a,i,size,n);
cout<<"after build"<<endl;
for(int i=0;i<n;i++)
cout<<"i="<<i<<"a[i]="<<a[i]<<endl;
}
void HeapSort(int a[],int n)
{
int size=n;
BuildMaxHeap(a,size,n);
for(int i=n-1;i>0;i--)//i=9,,,,1最后到a[1]交换一次元素即可
{
Swap(a[0],a[i]);
size = size-1;
MaxHeap(a,0,size,n);
}
}
void Swap(int & a,int & b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
return;
}

总结堆排序

把堆数据变成最大堆(BuildMaxHeap):倒着数对所有非叶子节点进行MaxHeap,完成整个二叉堆的最大堆化
从根节点开始,每次把根节点(最大数)放到数组结尾,然后再把这个根节点MaxHeap。
MaxHeap里面用一个size参数控制当前有几个没排序。

时间复杂度是O(nlogn)

猜你喜欢

转载自blog.51cto.com/13962698/2173119