数据结构--树(下)--堆

这里的堆不是堆栈,排队不完全按照时间的先后顺序,有优先的级别。排队的原则有哪些?

  优先队列:特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列 的先后顺序

那么怎么实现优先队列呢?数组或者是链表?见下图

是否可以用二叉树存储结构?

  二叉搜索树?  查找和删除都是树的高度log2n,可能一直删除最大值,但是删除几次之后,我们就不用查找树,搜索树。

还有别的方法吗?

  那我们怎么组织二叉树呢?

最好的 方法就是用完全二叉树。最大的特点就是用完全二叉树任何一个节点都比他的左右儿子结点大。

堆的两个特性

结构性:用数组表示的完全二叉树

有序性:任何一个节点都比他的左右儿子结点大。

  1. “最大堆”(MaxHeap)也称为“大顶堆”:最大值
  2. “最小堆”(MinHeap) 也称为“小顶堆”:最小值

最大堆的操作

首先,我们看一下,堆这个数据结构,我们怎么定义

typedef struct HeapStruct *MaxHeap;
struct{
    ElementType *Elements;    //存储堆元素的数组
    int Size;                //堆的当前元素个数
    int Capacity;            //堆的最大容量
}

最大堆的创建

MaxHeap Create(int MaxSize){
    MaxHeap H = malloc(sizeof(struct HeapStruct));
    H->Elements = malloc((MaxSize + 1)*sizeof(ElementType));    //这里因为堆是从下标为1开始的,不是0,所以申请数组空间的时候要+1
    H->Size = 0;
    H->Capacity = MaxSize;
    H->Elements[0] = MaxData;   //这里用作岗哨,用作哨兵用
    return H;
}

最大堆的插入  : 实质上是完全二叉树的插入

思路是:先把元素放在最后一个位置,以满足完全二叉树的结构性,然后再循环满足二叉树的有序性。

void Insert(MaxHeap H, ElentType item){
    int i;
    if (isfull(H)){
        printf("最大堆已满");
        return;
    }
    i = ++H->Size;
    for (; H->ElementType[i / 2); i /= 2)        //有一种情况:当我们比到第一个元素的时候,按照循环还要向前比较,如果我们不用哨兵可以 &&i>1
        H->Element[i] = H->Element[i / 2];        //这时候哨兵就有作用了,安排一个特别大的值做哨兵
    H->Elements[i] = item;                //就爱那个items
}

插入的时间复杂性呢是T(N) = O(log2N) ,就是树的高度

最大堆得删除

最大堆删除,删除的位置是确定的,一定是根的位置、

思路是,删除第一个元素,然后让完全二叉树的最后一个元素来替它满足二叉树的结构性,再来循环满足有序性

ElementType DeleteMax(MaxHeap H){
    int Parent, Child;
    ElementType MaxItem, temp;
    if (IsEmpty(H)){
        printf("最大堆为空");
        return;
    }
    MaxItem = H->Elements[1];
    temp = H->ElementType[H->Size--];    //这个循环的作用就是找到parents的位置
    for (Parent = 1; Parent * 2 <= H->Size; Parent = Child)
    {
        Child = Parent * 2;
        if (Child != H->Size && (H->Elments[Child] < H->ElmentType[Child + 1]))        //判断有没有右儿子,并且右儿子比左儿子大,则用右儿子
            Child++;
        if (temp >= H->Elments[Child]) break;
        else
            H->Elements[Parent] = H->Elements[Child];
    }
    H->Elements[Parent] = temp;
    return MaxItem;
}

时间复杂性还等于树的高度T(N) = log2n

最大堆得建立

  堆的一个应用:堆排序

建立最大堆:将已经存在的N个元素按最大堆的要求存放在一个一维数组中。

方法1、通过插入操作,将N个元素一个个相继插入到一个初始为空的堆中去。其时间代价为O(NlogN).

优化之后

方法2、在线性时间复杂度下建立最大堆。

  (1)将N个元素入,按输入顺序存先满足完全二叉树的结构特性

  (2)调整各节点位置,以满足最大堆的有序特性。

一点一点的调成堆

时间: 2024-08-03 16:43:19

数据结构--树(下)--堆的相关文章

【数据结构】第6章 树(下)

数据结构第6章 树(下) §6.4 树和森林 6.4.1 树的储存结构 ①父亲表示法(利用每个(除根)结点只有唯一的父亲的性质) ②孩子表示法(用广义表实现) ③孩子兄弟表示法(二叉链表指向第一个孩子结点和下一个兄弟结点) 6.4.2森林与二叉树的转换 二叉树和树都可以用二叉链作为储存结构(分别是孩子表示法和孩子兄弟表示法),给定一棵树,可以找到唯一的一棵二叉树与之对应.两者的物理结构是相同的,只是解释不同而已(旋转). 任何一棵和树对应的二叉树,其右子树必空(因为根是没有兄弟的),在森林中可以

数据结构 树(下)

数据结构 树(下) 一.概述 AVL树.伸展树.红黑树搜索树算法保证最坏情况或者一系列操作情况下,搜索.插入和删除的操作的时间复杂度是O(logn).本文主要内容包含:平衡搜索树中的AVL树.伸展树.(2,4)树.红黑树 和(a,b)树.B树等实际运用的树数据结构. 二叉搜索树的删除 二.AVL树 1.基本知识 1.AVL树是维持对数O(logn)的高度的特殊二叉搜索树.“高度”指根节点到叶子节点最长路径上的节点的数量.“None”的孩子的高度是0,叶子节点的高度是1,父节点是叶子节点的高度加1

数据结构--树(定义与存储结构)

树基本定义 树的定义 数是具有n个节点的有限集.如图即是一个树形结构. 节点分类 节点的度:一个节点拥有的子节点即成为节点的度,比如A节点,有B和C两个子节点,那么A节点的度=2. 叶节点(终端节点):没有子节点的节点,比如G.H.I.... 如图: 节点间关系 孩子节点:某一个节点的子节点称为孩子节点.比如B.C节点是A节点的孩子节点. 双亲节点:与孩子节点相反.比如,A节点是B.C的双亲节点. 兄弟节点:同一个双亲节点的孩子节点,之间称为兄弟节点.比如,B.C为兄弟节点. 如图: 树的存储结

一步一步写算法(之哈夫曼树 下)

原文:一步一步写算法(之哈夫曼树 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题.但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计).所以,我们所要做的就是编写compare和swap两个函数.通用冒泡代码如下所示, void bubble_sort(void* array[], int le

数据结构---树、二叉树、森林

1.基本术语: 度:有两种度"结点的度"与"树的度".结点的度指的是一个结点子树的个数:树的度是指树中结点度的最大值. 叶子结点:指的是没有子树的结点. 层:树是有层次的,一般根结点为第0层.规定根结点到某结点的路径长度为该结点的层数. 深度:树中结点的最大层数 兄弟:同一双亲的结点,互为兄弟 堂兄弟:双亲在同一层次的结点,互为堂兄弟 祖先:从根结点到该结点的路径上的所有结点都是该结点的祖先. 子孙:以某一结点为根的子树上的所有结点都是该结点的子孙 森林:n棵互不相

2017-2018 20172309 《程序设计与数据结构(下)》第七章学习总结

2017-2018 20172309 <程序设计与数据结构(下)>第七章学习总结 一.教材学习内容总结 1.1关于二叉查找树的一些概念 二叉查找树具有附加属性,其左孩子小于父节点.而父节点又小余或者等于右结点. 因此二叉查找树的最右侧会存放最大元素.而其最左侧会存放最小元素. 二叉查找树是二叉树的扩展,它绝大数方法都会用到递归,二叉查找树的平均查找深度为O(log2N). 1.2实现二叉查找树 添加元素(addElement操作) 插入方法首先在插入的时候判断被插入元素的类型是不是Compar

数据结构——树状数组

我们今天来讲一个应用比较广泛的数据结构——树状数组 它可以在O(nlogn)的复杂度下进行单点修改区间查询,下面我会分成三个模块对树状数组进行详细的解说,分别是树状数组基本操作.树状数组区间修改单点查询的实现.树状数组查询最值的实现 一. 树状数组一般分为三种操作,初始化.修改.查询 在讲基本操作之前,我们先来看一张图 这张图就是树状数组的存储方式,对于没有接触过树状数组的人来说看懂上面这张图可能有些困难,上图的A数组就是我们的原数组,C数组则是我们需要维护的数组,这样存储能干什么呢,比如我们在

数据结构 树(上)

数据结构 树(上) 一.概述 主要内容包含树的基本概念.二叉树(平衡二叉树.完全二叉树.满二叉树).搜索树(二叉搜索树.平衡搜索树.AVL树.伸展树.(2,4)树.红黑树).(a,b)树.B树等实际运用的树数据结构 二.基本知识(树的定义和属性) 1.树(非线性数据结构)运用于一些算法实现的效率会比线性数据结构(基于数组的列表和链表)快,广泛运用于文件系统目录结构.图形用户界面.MySQL数据库索引.网站.路由协议和其他计算机系统中 2.树T定义为存储一系列元素的有限节点集合,这些节点具有 pa

数据结构之基于堆的优先队列

优先队列的最重要的操作:删除最大元素(或最小)和插入元素.数据结构二叉堆能够很好的实现队列的基本操作.二叉堆的结点按照层级顺序放入数组,用长度为N+1的私有数组pq来表示一个大小为N的堆(堆元素放在pq[1]至pq[N]之间,为方便计数,未使用pq[0]),跟节点在位置1,它的子结点在位置2和3,以此类推.位置k的节点的父节点位置为k/2,它的两个子节点位置分别为2k和2k+1.当一颗二叉树的每个节点都大于等于它的两个子节点时,称为大根堆.当一颗二叉树的每个节点都小于等于它的两个子节点时,称为小

Windows环境下堆管理系统的快表介绍

实验环境: 操作系统: Windows 2000 Service Pack 4 集成开发环境: Microsoft Visual C++ 6.0 SP6 构建版本:Release版本 实验代码: 1 #include <stdio.h> 2 #include <windows.h> 3 4 void main() 5 { 6 HLOCAL h1, h2, h3, h4; 7 HANDLE hp; 8 9 // 启用快表 10 hp = HeapCreate(0, 0, 0); 11