数据结构 树的基本概念 7

目录:树和二叉树

1) 树的基本知识                       2)二叉树                          3)遍历二叉树和线索二叉树

4)树和森林                            5)赫夫曼树及其应用


                                         数据结构 树的基本概念 7

特点:非线性结构,一个直接前驱,但可能有多个直接后继(1:n)

1.树的定义         

        由一个或多个(n≥0)结点组成的有限集合T,有且仅有一个结点称为根(root),当n>1时,其余的结点分为m(m≥0)个互不相交的有限集合T1,T2,…,Tm。每个集合本身又是棵树,被称作这个根的子树 。       

                                               数据结构 树的基本概念 7

注1:过去许多书籍中都定义树为n≥1,曾经有“空树不是树”的说法,但现在树的定义已修改。

注2:树的定义具有递归性,即树中还有树。

2.若干术语

数据结构 树的基本概念 7

根——即根结点(没有前驱) 

叶子——即终端结点(没有后继)

森林——指m棵不相交的树的集合(例如删除A后的子树个数)

有序树——结点各子树从左至右有序,不能互换(左为第一)

无序树——结点各子树可互换位置

双亲——即上层的那个结点(直接前驱) parent

孩子——即下层结点的子树 (直接后继) child

兄弟——同一双亲下的同层结点(孩子之间互称兄弟)sibling

堂兄弟——即双亲位于同一层的结点(但并非同一双亲)cousin

祖先——即从根到该结点所经分支的所有结点

子孙——即该结点下层子树中的任一结点

结点——即树的数据元素

结点的度——结点挂接的子树数(有几个直接后继就是几度,亦称“次数”)

结点的层次——从根到该结点的层数(根结点算第一层)

终端结点——即度为0的结点,即叶子

分支节点——除树根以外的结点(也称为内部结点)

树的度——所有结点度中的最大值(Max{各结点的度})

树的深度(或高度)——指所有结点中最大的层数(Max{各结点的层次})

问:右上图中的结点数=13  ;树的度= 3 ;树的深度=4

3.树的表示法

图形表示法       嵌套集合表示法         广义表表示法         目录表示法           左孩子-右兄弟表示法

图形表示法:

数据结构 树的基本概念 7

广义表表示法:

数据结构 树的基本概念 7

( A ( B ( E ( K, L ), F ), C ( G ), D ( H ( M ), I, J ) ) ) 根作为由子树森林组成的表的名字写在表的左边

数据结构 树的基本概念 7

4.树的抽象数据类型定义

数据结构 树的基本概念 7

树的逻辑结构(特点): 一对多(1:n),有多个直接后继(如家谱树、目录树等等),但只有一个根结点,且子树之间互不相交。

树的存储结构:

讨论1:树是非线性结构,该怎样存储?

           —仍然有顺序存储、链式存储等方式。

讨论2:树的顺序存储方案应该怎样制定?

可规定为:从上至下、从左至右将树的结点依次存入内存。 重大缺陷:复原困难(不能唯一复原就没有实用价值)。

讨论3:树的链式存储方案应该怎样制定?

可用多重链表:一个前趋指针,n个后继指针。 细节问题:树中结点的结构类型样式该如何设计?  即应该设计成“等长”还是“不等长”? 缺点:等长结构太浪费(每个结点的度不一定相同);       不等长结构太复杂(要定义好多种结构类型)。

讨论4:计算机如何实现各种不同进制的运算?

实现思路:先研究最简单、最有规律的二进制运算规律,然后设法把各种不同进制的运算转化二进制运算。

讨论5:树的存储可否借鉴这种思路呢?

解决思路:先研究最简单、最有规律的树,然后设法把一般的树转化为这种简单的树。

树的运算:

要明确:

1. 普通树(即多叉树)若不转化为二叉树,则运算很难实现。

2. 二叉树的运算仍然是插入、删除、修改、查找、排序等,但这些操作必须建立在对树结点能够“遍历”的基础上!  

(遍历——指每个结点都被访问且仅访问一次,不遗漏不重复)。

5.二叉树

为何要重点研究每结点最多只有两个 “叉” 的树?

二叉树的结构最简单,规律性最强; 可以证明,所有树都能转为唯一对应的二叉树,不失一般性。

二叉树的定义:

定义:是n(n≥0)个结点的有限集合,由一个根结点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成 。

逻辑结构:  一对二(1:2)

基本特征: ① 每个结点最多只有两棵子树(不存在度大于2的结点); ② 左子树和右子树次序不能颠倒(有序树)。

基本形态:

数据结构 树的基本概念 7

二叉树的抽象数据类型定义:

数据结构 树的基本概念 7

6.二叉树的性质

数据结构 树的基本概念 7

讨论3:二叉树的叶子数和度为2的结点数之间有关系吗?

性质3: 对于任何一棵二叉树,若2度的结点数有n2个,则叶子数(n0)必定为n2+1 (即n0=n2+1)

证明: ∵ 二叉树中全部结点数n=n0+n1+n2(叶子数+1度结点数+2度结点数) 又∵二叉树中全部结点数n=B+1 ( 总分支数+根结点 )        (除根结点外,每个结点必有一个直接前趋,即一个分支) 而 总分支数B= n1+2n2  (1度结点必有1个直接后继,2度结点必有2个) 三式联立可得: n0+n1+n2= n1+2n2 +1,   即n0=n2+1 实际意义:叶子数=2度结点数+1

满二叉树:

数据结构 树的基本概念 7

数据结构 树的基本概念 7

数据结构 树的基本概念 7

对于两种特殊形式的二叉树(满二叉树和完全二叉树),还特别具备以下2个性质:

数据结构 树的基本概念 7

数据结构 树的基本概念 7

数据结构 树的基本概念 7

数据结构 树的基本概念 7

数据结构 树的基本概念 7

7.二叉树的存储结构

一、顺序存储结构

按二叉树的结点“自上而下、从左至右”编号,用一组连续的存储单元存储。

问:顺序存储后能否复原成唯一对应的二叉树形状?

答:若是完全/满二叉树则可以做到唯一复原。而且有规律:下标值为i的双亲,其左孩子的下标值必为2i,其右孩子的下标值必为2i+1(即性质5)    

例如,对应[2]的两个孩子必为[4]和[5],即B的左孩子必是D,右孩子必为E。

数据结构 树的基本概念 7

数据结构 树的基本概念 7

二、链式存储结构

用二叉链表即可方便表示,一般从根结点开始存储。 (相应地,访问树中结点时也只能从根开始)

注:如果需要倒查某结点的双亲,可以再增加一个双亲域(直接前趋)指针,将二叉链表变成三叉链表。

二叉树结点数据类型定义:

typedef struct node *tree_pointer;
typedef struct node{
        int data;
        free_pointer lefet_child,right_child;
}node;

数据结构 树的基本概念 7

二叉链表示法: 

 

                                                                     数据结构 树的基本概念 7

                                                             数据结构 树的基本概念 7

                                                              数据结构 树的基本概念 7

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
/*
typedef struct BiTNode
{
    int date;
    struct BiTNode* lchild,* rchild;
}BiTNode,*BiTree;
*/
//二叉链表示法
struct BiTNode
{
    int date;
    struct BiTNode* lchild,* rchild;
}BiTNode,*BiTree;
typedef struct BiTNode BiTNode;

typedef struct BiTNode *BiTree;
void main()
{
    BiTNode *p1,*p2,*p3,*p4,*p5;
    p1=( BiTNode *)malloc(sizeof(BiTNode));
    p2=( BiTNode *)malloc(sizeof(BiTNode));
    p3=( BiTNode *)malloc(sizeof(BiTNode));
    p4=( BiTNode *)malloc(sizeof(BiTNode));
    p5=( BiTNode *)malloc(sizeof(BiTNode));

    p1->data=1;
    p2->data=2;
    p3->data=3;
    p4->data=4;
    p5->data=5;

    //建立关系
    p1->lchild=p2;
    p1->rchild=p3;
    p2->lchild=p4;
    p3->lchild=p5;

    //树的遍历

    return;
}

三叉链表示法:

                                                    数据结构 树的基本概念 7

                                                                   数据结构 树的基本概念 7

                                             数据结构 树的基本概念 7

//三叉链表
typedef struct TriTNode
{
     int data;
     //左右孩子指针
     struct TriTNode *lchild,*rchild;
     struct TriTNode *parent;
}TriTNode,*TriTree;

双亲链表法:

数据结构 树的基本概念 7

//双亲链表
#define MAX_TREE_SIZE 100
typedef struct BPTNode
{
	int data;
	int parentPosition;  //指向双亲的指针   //数组下标
	char LRTag;     //左右孩子标志域
}BPTNode;

typedef struct BPTree
{
	BPTNode nodes[100];    //因为节点之间是分散的,需要把节点存储到数组中
	int num_node;    //节点数目
	int root;     //根节点的位置   //注意此域存储的是父亲节点在数组的下标
}BPTree;

void main()
{
	BPTree tree;

	//根节点
	tree.nodes[0].parentPosition = 1000;

	//B
	tree.nodes[1].parentPosition = 0;
	tree.nodes[1].data = 'B';
	tree.nodes[1].LRTag = 1;

	//C
	tree.nodes[2].parentPosition = 0;
	tree.nodes[2].data = 'C';
	tree.nodes[2].LRTag = 2;
	system("pause");
}