简单易懂的 :树的介绍+二叉树的介绍+堆的介绍+完全二叉树(堆)的实现;

一:树的概念

树是一种非线性的数据结构,它由n(n>0)个有限节点组成的一个具有层次的关系集合。

那么为什么把它叫做树呢?

这是因为它的结构看起来就像是一颗倒挂起来的树;如下图

 

 接下来我们就看看树节点的一些概念

在一个n个节点的树包含一个根节点和n-1个非根节点,如上图所示,1就是该树的根节点;

而一个非根节点有且只有一个父节点,例如上图,2的父节点是1,7的父节点是3,而每一个节点具有一个或多个子节点;

且出了根节点外,每个子结 点可以分为多个不相交的子树 ;比如以2为节点,(4,8,9)和(5,10)两个子树

如下图:

关于树还有以下感念;

节点的度:一个节点含有的子树的个数称为该节点的度;如上图:2节点的度就是3,7的度是2;

非终端节点或分支节点:度不为0的节点; 如上图:1,2,3,4,5,7都是分支节点

兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:11,12是兄弟节点

树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为3

节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

树的高度或深度:树中节点的最大层次; 如上图:树的高度为4

堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:9、10互为兄弟节点

节点的祖先:从根到该节点所经分支上的所有节点;如上图:1是所有节点的祖先 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是1的子孙

森林:由m(m>=0)棵互不相交的树的集合称为森林

二:树与非树

请看图一图二:他们还是树吗?

答案是不是的,因为他们违反了以下树的规定

1:子树是不相交的

2:出了根节点,其他节点有且只有一个父节点

3:一个有n个节点的树有n-条边(两个节点之间的连接线)

三:树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表 示法,孩子表示法、孩子兄弟表示法等等。阿鲤在这里这里就简单的了解其中最常用的孩子兄弟表示法

代码:

typedef int DataType;
struct Node
{
	struct Node *_FirstChild; //指向第一个子节点
	struct Node *_NextBother; //指向下一个兄弟节点
	DataType data;            //节点中的数据域
};

图解:

四:二叉树的介绍

1:二叉树的概念

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树 的二叉树组成。

2:二叉树的特点

1. 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。

2. 二叉树的子树有左右之分,其子树的次序不能颠倒

如图:

特殊二叉树:

满二叉树:所有的父节点都有两个节点(左子节点和右子节点)

完全二叉树:最后一个节点的之前的父节点都是满节点

如图:

二叉树的性质:

1:若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2的(i-1)次方(>0)个结点

2:若规定只有根节点的二叉树的深度为1,则深度为K的二义树的最大结点数是2的K次方减1(k>=0)

3:对任何一棵二叉树,如果其叶结点个数为nO.度为2的非叶结点个数为n2,则有no=n2+ 1

4:具有n个结点的完全二叉树的深度k为log2(n+1)上取整

5:对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序
对所有节点从0开始编号,则对于序号为i的结点有有
    1:若i>0,双亲序号: (i-1)/2;:
         i=0为根节点编号,无双亲结点
    2:若2i+1<n,左孩子序号:2i+1否则无左孩子

    3.   若2i+2<n,右孩子序号2i+2否则无右孩子

五:堆的介绍

堆的概念:

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆

图解:

存储:小堆:1,5,7,6,6,9                  大堆:8,7,3,4,2,0

六:堆的实现(完全二叉树的实现)

直接上代码

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int HDataType;
typedef int(*Compare) (HDataType, HDataType); 

int Less(HDataType left, HDataType right)//compare of little heap 
{
  return left<right;
}

int Great(HDataType left, HDataType right)//compare of bit heap 
{
  return left>right;
}

typedef struct Heap//Heap structure
{
  HDataType *_array;
  int _capacity;
  int _size;
  Compare _comp;
}Heap;

void InitHeap(Heap *hp,Compare comp)//Initalization of heap 
{
  assert(hp);
  hp->_array = (HDataType*)malloc(sizeof(HDataType)*3);
  hp->_capacity = 3;
  hp->_size = 0;
  hp->_comp = comp;
}


int Swap(HDataType *left, HDataType *right)
{
  int tmp = *left;
  *left = *right;
  *right = tmp; 
}

void CheckCapacity(Heap*hp)//Inspection capacity 
{
  assert(hp);
  if(hp->_capacity == hp->_size)
  {
    int newcapacity = 2*hp->_capacity;
    HDataType *arr = (HDataType*)realloc(hp->_array,sizeof(HDataType)*newcapacity);
    if(NULL == arr)
    {
      assert(0);
      return;
    }
    hp->_array = arr;
    hp->_capacity = newcapacity;
  }
}

void Adjustup(HDataType *array, int child, Compare comp)//Upword adujutment  
{
    int parent = (child-1)/2;
    while(child)
    {
      if(comp(array[child], array[parent]))
      {
        Swap(&array[child], &array[parent]);
        child = parent;
        parent = (child-1)/2;
      }
      else 
      {
        return;
      }
    }
}

void InsertHeap(Heap*hp, HDataType data)//insert
{
  assert(hp);
  CheckCapacity(hp);//Inspection capacity
  hp->_array[hp->_size++] = data;
  Adjustup(hp->_array, hp->_size-1, hp->_comp);
}

void ShowHeap(Heap*hp)
{
  int count = 0;
  while(count < hp->_size)
  {
    printf("%-3d",hp->_array[count]);
    count++;
  }
}

int main()
{
  Heap hp;
  InitHeap(&hp, Great);//Initalization
  InsertHeap(&hp, 1);
  InsertHeap(&hp, 4);
  InsertHeap(&hp, 2);
  InsertHeap(&hp, 3);
  InsertHeap(&hp, 9);
  InsertHeap(&hp, 5);
  InsertHeap(&hp, 7);
  InsertHeap(&hp, 1);
  InsertHeap(&hp, 10);
  InsertHeap(&hp, 6);
  InsertHeap(&hp, 3);
  ShowHeap(&hp);
  return 0;
}

图解:以小堆为例

这样多次循环插入就可以完成小堆的实现了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值