完全二叉树,堆,堆排序,优先队列

完全二叉树

1、定义:对树中结点从上到下从左到右顺序进行编号,且编号为i的结点与完美二叉树中编号为i的结点在二叉树中位置相同。

2、完全二叉树的特点:

(1) 叶结点只能出现在下层和次下层且最下层的叶子结点出现在树的左部。

(2) 由特性,适合以数组的形式进行存储,并且父节点和左右儿子有一定关系便于访问。

 

        #define LEFT(i)   (i*2)
        #define RIGHT(i)  (i*2+1)
        #define PARENT(i) (i/2)

 

(3) 当以数组形式存储n个元素时,叶结点下标分别是 [n/2]+1  [n/2]+2……n。即叶结 点个数为n/2个。

(4) 具有n个结点的完全二叉树深度为 k = lgn上取整。(根节点深度为1)高度 k = lgn(下取整)

(5) 在高度为h的完全二叉树中元素个数   2^(h ). <=  n  <= 2^(h+1)- 1  (叶结点高度为0),在高度为h的完全二叉树中元素个数  2^(h -1 )<=  n  <=  2^(h)- 1 

(6) 在一个含有n个元素的完全二叉树中,至多有(n/ 2 ^(h+1))向上取整  个高度为h的结点。  至多有 2^(h-1)个 深度为h的结点。

(7) 在完全二叉树中  n0 = n2 + 1,    n = 2 * n0 - 1  +  1 或者  n = 2 * n0 - 1  取决于    叶结点是偶数还是奇数。

 

 

堆是一种特殊的完全二叉树。

1 结构性:(二叉)堆是一个数组,他可以被看成一个完全二叉树。

2.有序性:从任意一个点顺着路径到另一个点关键字权值总是非递增或者非递减的

兄弟之间并不存在特定的约束关系。当为最小堆时,满足  A[PARENT(i)] <= A[i]。

对于一个最大堆  , 最大的元素在树根处, 最小的元素在叶结点中。

 

以最大堆为例:

一、维护堆的性质:

1、下渗: 0 (lg n)

前提 LEFT(i) 和 RIGHT(i) 子树 必须为最大堆。

 

void PercolateDown(MaxHeap H,Position i)//下滤  
{
if(H == NULL) return ;
//从左右孩子和父母中找到最大的
int L = LEFT(i), R = RIGHT(i), larget;
    //同时处理了只有一个左子树和没有儿子的这两种特殊情况 
if(L <= H->size && H->array[L] > H->array[i]) larget = L;
    else larget = i;
if(R <= H->size && H->array[R] > H->array[larget]) larget = R;
//如果这个最大值为父母 找到位置 停止递归 
if(larget != i)
{
EXCHANGE(H->array[larget],H->array[i]);
PercolateDown(H, larget);
}
return ;
} 

 

 

 

2、上渗: 0 (lg n)

满足 在该层i左边的所有元素以及上多层的元素都满足堆的性质。

 

void PercolateUp(MaxHeap H,Position i)//上滤 
{
if(H == NULL) return ;
//与其父母比较 是否交换,直到找到位置为止
while(i > 1 && H->array[i] > H->array[PARENT(i)] )
{
EXCHANGE(H->array[i],H->array[PARENT(i)]);
i = PARENT(i);
} 
}

 

 

 

二、建堆:

1、用下渗方法建堆0(lgn)

 

void BuildMaxHeap(MaxHeap H) 
{
if(H == NULL) return ;
int i = H->size/2;
while(i>=1)
{
PercolateDown(H,i);
i--;
}
}

 

 

 

 

 

用上渗方法建堆:0(lgn)

 

void BuildMaxHeap(MaxHeap H) 
{
if(H == NULL) return ;
int i =1;
while(i<=H->size)
{
PercolateUp( H, i);
i++;
 } 
}

 

 

 

堆排序:0(nlgn)

 

void HeapSort(MaxHeap H)
{
if(H == NULL) return ;
int i = H->size;
BuildMaxHeap(H);  // 建好堆
while(i>=2)
{
EXCHANGE(H->array[1],H->array[H->size]);
H->size--;
PercolateDown(H,1);
i--;
}
} 

 

 

 

 

 

堆排序时间复杂度为0(nlgn)空间复杂度为0(1)但是不稳定的。

 

 

 

优先队列

一、增加一个元素:

由于在堆中增加一个元素,所以可以用想上渗透来维持堆的性质

 

void Insert(MaxHeap H,ElementType item)
{
if(H == NULL) return ;
H->array[++H->size] = item; H->printSize++;
PercolateUp(H,H->size);  
}

 

 

 

 

 

 

二、删除:

在删除时,要明确在执行上渗或下渗时堆的大小(减一)

 

1、删除顶部元素:

 

ElementType DeleteTop(MaxHeap H)
{
if(H == NULL) return 0 ;
ElementType item = H->array[1];
H->array[1] = H->array[H->size];
H->size--;  // 位置不能出现在下一句之后 否则 还是在原来的堆中进行维护 
PercolateDown(H,1);
return item;
}

 

 

 

2、删除某个元素:

向上渗透的办法:

现将这个元素变大使得上移到顶部,用DeleteTop(H);删除。

 

void IncreaseKey(MaxHeap H,Position X,int increaseItem)
{
if(H == NULL) return ;
H->array[X] -=increaseItem;
PercolateUp(H,X);
}
 
void Delete(MaxHeap H,Position X)
{
if(H == NULL) return ;
IncreaseKey(H,X,MAX);
DeleteTop(H);
}
*****************************************
向下渗透: //不成立 因为 当最后一个结点位于另一个子树中而删除的结点在别的子树中这样破坏堆。
void Delete(MaxHeap H,Position X)
{
if(H == NULL) return ;
H->array[X] = H->array[H->size];
H->size--;
PercolateDown(H,X);
}**************************************

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值