CH5-树和二叉树


20220112171655

5.1树和二叉树

20220112171835

5.1.1 树的定义

20220112171930

20220112172058

20220112172152

5.1.2基本术语

20220112172349

  • 树的深度: 树中结点的最大层次

  • 有序树: 树中结点的各子树从左至右有次序(最左边的为第一个孩子)。

  • 无序树: 树中结点的各子树无次序

20220112172642

20220112172828

5.1.3二叉树的定义

20220112172944

20220112173104

20220113103915

20220113104036

5种基本形态

20220113104141

5.2案例引入

案例1∶数据压缩问题

20220113104651

案例2︰求解表达式的值

20220113104607

5.3抽象数据类型定义

20220113104950

20220113105103

5.4二叉树的性质

性质1

20220113105345

20220113105423

性质2

20220113105658

性质3

20220113110134

两种特殊形式的二叉树

20220113110524

5.4.1满二叉树

20220113110904

20220113111023

5.4.2完全二叉树

20220113111219

20220113111432

20220113111518

20220113111720

性质4

20220113112133

20220113112250

性质5

20220113113429

20220113113556

5.5存储结构

20220113113659

5.5.1顺序

20220113113932

//二叉树顺序存储表示#define MAXTSIZE 100
Typedef TElemType SqBiTree[MAXSTIZE]
SqBiTree bt;

20220113114238

20220113114340

20220113114601

实现

#include <stdio.h>
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"

#define MAXSIZE 100
#define MAX_TREE_SIZE 100
typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int TElemType;  /* 树结点的数据类型,目前暂定为整型 */
typedef int SqBiTree[MAX_TREE_SIZE];/* 0号单元存储根结点  */

typedef struct{
    /* 结点的层,本层序号(按满二叉树计算) */
    int level,order;
}Position;

//假设整数0代表为空
int Nil = 0;

//构造空的二叉树,因为T是固定数组,不会改变,故不需要&
Status InitBiTree(SqBiTree T){
    int i;
    for(i=0; i<MAX_TREE_SIZE; i++){
        T[i] = Nil; //初始值为空
    }
    return 1;
}

//按层序次序输入二叉树的节点的值(字符型或整形),构造顺序存储二叉树
Status CreateBiTree(SqBiTree T){
    int i =0;
    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n",MAX_TREE_SIZE);
    while(i<=10){
        T[i] = i+1;
        if(i!=0&&T[(i+1)/2-1] == Nil&&T[i]!=Nil){
            printf("出现了无双亲且非根节点%d\n",T[i]);
            exit(0);
        }
        i++;
    }
    //然后将后面的值赋值为空
    while(i<MAX_TREE_SIZE){
        T[i] = Nil;
        i++;
    }
    return 1;
}

//清空二叉树,在顺序存储中,两函数完全一样
#define ClearBiTree InitBiTree

/* 初始条件: 二叉树T存在 */
/* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
Status BiTreeEmpty(SqBiTree T){
    if(T[0] == Nil){
        return 1;
    }
    return 0;
}

/* 初始条件: 二叉树T存在。
操作结果: 返回T的深度 */
Status BiTreeDepth(SqBiTree T){
    //性质2:深度为k的二叉树至多有2^k个节点
    int k = 0;
    while(powl(2,k)<=(10+1)){
        k++;
    }
    return k;
}

/* 初始条件: 二叉树T存在 */
/* 操作结果:  当T不空,用e返回T的根,返回OK;否则返回ERROR,e无定义 */
Status Root(SqBiTree T){
    TElemType root;
    if(BiTreeEmpty(T)){
        return 0;
    }else{
        root = T[0];
        return root;
    }
}

/* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
/* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
Status Value(SqBiTree T,Position e){
    if(e.order <= powl(2,e.level-1)) //不超过每层的节点数
        return T[(int)powl(2,e.level-1)+e.order-2];
    else
        return 0;
}

/* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
/* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */
Status Assign(SqBiTree T,Position e,TElemType value){
    int index = (int)powl(2,e.level-1)+e.order-2;
    //值不为空,且双亲节点不存在时
    if(value!= Nil&&T[(index+1)/2-1]==Nil){
        return 0;
    }
    /*  给双亲赋空值但有叶子 */
    else if(value == Nil && (T[index*2+1]!=Nil || T[index*2+2]!=Nil)){
        return 0;
    }
    T[index] = value;
    return 1;
}

//求一个节点的双亲节点
TElemType Parent(SqBiTree T,Position e){
    int index = 0;
    index = (int)powl(2,e.level-1)+e.order-2;
    //为空树或者只有根节点
    if(T[0] == Nil ||(T[2*index+1]==Nil || T[2*index+2]==Nil)){
        return 0;
    }else{
        if(index%2==0)
            return T[index/2-1];
        else
            return T[index/2];
    }
    return 0;
}

//求一个节点的左孩子节点
TElemType LeftChild(SqBiTree T,Position e){
    int index = 0;
    index = (int)powl(2,e.level-1)+e.order-2;
    if(T[0] == Nil ||(T[2*index+1]==Nil || T[2*index+2]==Nil)){
        return 0;
    }else{
        return T[2*index+1];
    }
}

//求一个节点的右孩子节点
TElemType RightChild(SqBiTree T,Position e){
    int index = 0;
    index = (int)powl(2,e.level-1)+e.order-2;
    if(T[0] == Nil ||(T[2*index+1]==Nil || T[2*index+2]==Nil)){
        return 0;
    }else{
        return T[2*index+2];
    }
}


//求一个节点的左兄弟节点
TElemType LeftSibling(SqBiTree T,Position e){
    int index = 0;
    index = (int)powl(2,e.level-1)+e.order-2;
    if(T[0] == Nil ||(T[2*index+1]==Nil || T[2*index+2]==Nil)){
        return 0;
    }else{
        if(index%2==0)
            return T[index-1];
        else
            return 0;
    }
}

//求一个节点的右兄弟节点
TElemType RightSibling(SqBiTree T,Position e){
    int index = 0;
    index = (int)powl(2,e.level-1)+e.order-2;
    if(T[0] == Nil ||(T[2*index+1]==Nil || T[2*index+2]==Nil)){
        return 0;
    }else{
        if(index%2==0){
            return 0;
        }
        else
            return T[index+1];
    }
}
//////////////////////////遍历////////////////////////////
//先序遍历的原则(递归):
void PreTraverse(SqBiTree T,int index){
    printf("%d ",T[index]);
    if(T[2*index+1]!=Nil){
        PreTraverse(T,2*index+1);
    }
    if(T[2*index+2]!=Nil){
        PreTraverse(T,2*index+2);
    }
}
void PreOrderTraverse(SqBiTree T){
    if(!BiTreeEmpty(T)){
        PreTraverse(T,0);
    }
    printf("\n");
}

//中序遍历原则:
void InTraverse(SqBiTree T,int index){

    if(T[2*index+1]!=Nil){
        InTraverse(T,2*index+1);
    }
    printf("%d ",T[index]);
    if(T[2*index+2]!=Nil){
        InTraverse(T,2*index+2);
    }
}
void InOrderTraverse(SqBiTree T){
    if(!BiTreeEmpty(T)){
        InTraverse(T,0);
    }
    printf("\n");
}

//后序遍历原则:
void PostTraverse(SqBiTree T,int index){

    if(T[2*index+1]!=Nil){
        PostTraverse(T,2*index+1);
    }
    if(T[2*index+2]!=Nil){
        PostTraverse(T,2*index+2);
    }
    printf("%d ",T[index]);
}
void PostOrderTraverse(SqBiTree T){
    if(!BiTreeEmpty(T)){
        PostTraverse(T,0);
    }
    printf("\n");
}



int main(){

    SqBiTree T;
    InitBiTree(T);
    //创建二叉树
    CreateBiTree(T);

    //判断是否为空
    printf("二叉树是否为空:%d\n",BiTreeEmpty(T));

    //清空二叉树后
    //判断是否为空
    printf("二叉树是否为空:%d\n",ClearBiTree(T));
    //重新创建二叉树
    CreateBiTree(T);

    //树的深度
    printf("树的深度:%d\n",BiTreeDepth(T));

    //树根
    printf("树的根节点:%d\n",Root(T));

    //寻找某一层某个特地的元素
    Position e;
    e.level = 2;
    e.order = 2;
    printf("2层第2个是:%d\n",Value(T,e));

    //修改节点元素
    Assign(T,e,50);
    printf("2层第2个是:%d\n",Value(T,e));

    //求节点双亲
    printf("2层第2个的双亲是:%d\n",Parent(T,e));

    //求节点左孩子
    printf("2层第2个的左孩子是:%d\n",LeftChild(T,e));

    //求节点右孩子
    printf("2层第2个的左孩子是:%d\n",RightChild(T,e));


    //求节点左兄弟
    printf("2层第2个的左兄弟是:%d\n",LeftSibling(T,e));
    //求节点右兄弟
    printf("2层第2个的右兄弟是:%d\n",RightSibling(T,e));


    //先序遍历
    printf("先序遍历\n");
    PreOrderTraverse(T);

    //中序遍历
    printf("中序遍历\n");
    InOrderTraverse(T);

    //后序遍历
    printf("后序遍历\n");
    PostOrderTraverse(T);
    return 0;
}

20220125103737

5.5.2链式

二叉链表

20220113114804

typedef struct BiNode{
    TElemType data;
	struct BiNode *lchild, *rchild;		//左右孩纸
}BiNode,*BiTree;

20220113125117

20220113130141

三叉链表

20220113130309

typedef struct TriTNode{
    TelemType data;
	struct TriTNode *lchild,*parent,*rchild;
 }TriTNode,*TriTree;

5.6遍历二叉树

20220113131507

5.6.1.遍历二叉树

20220113132612

20220113132822

20220113133000

先序遍历

20220113133107

中序遍历

20220113133240

后序遍历

20220113133328

20220113133708

20220113134241

5.6.2遍历序列

20220113134600

例题1

20220113135236

20220113135303

20220113135330

例题2

20220113140346

5.6.3算法实现

【算法1】:先序

20220113141512

Status PreOrderTraverse(BiTree T){
    if(T==NULL)	return OK;		//空二叉树
    else{
        visit(T);					//访问根结点
        PreOrderTraverse(T->lchild);//递归遍历左子树
        PreOrderTraverse(T->rchild);//递归遍历右子树
    }
}
void Pre(BiTree *T) {
    if (T!=NULL) {
        printf("%d\t",T->data);
        pre(T->lchild);
        pre(T->rchild);
    }
}

20220113142059

【算法2】:中序

20220113142401

Status InOrderTraverse(BiTree T){
    if(T==NULL) return OK;//空二叉树
    else{
        InOrderTraverse(T->lchild);//递归遍历左子树
        visit(T);//访问根结点;
        InOrderTraverse(T->rchild);//递归遍历右子树}
    }
}

【算法3】:后序

20220113143037

Status PostOrderTraverse(BiTree T){
    if(T==NULL) return OK;//空二叉树
    else{
    	PostOrderTraverse(T->lchild);//递归遍历左子树
        PostOrderTraverse(T->rchild);//递归遍历右子树
        visit(T);//访问根结点
    }
}

算法分析

20220113143423

20220113143624

20220113144238

【算法4】:中序非递归

20220113164322

Status InOrderTraverse (BiTree T) {
    BiTree p; InitStack(S); p=T;
    while(p || !StackEmpty(S)) {
    	if(p) { 
            Push(S,p);
            p = p->lchild;
        }
        else { 
            Pop(S,q); 
            printf(“%c”,q->data);
            p= q->rchild;
        }
    }
    return OK;
}

【算法5】:层次遍历

20220113170345

20220113171523

typedef struct{
	BTNode data[MaxSize];	//存放队中元素
    int front,rear;		   //队头和队尾指针
} SqQueue;					//顺序循环队列类型

void LevelOrder(BTNode *b) {
    BTNode *p;	SqQueue *qu;
    InitQueue(qu);	//初始化队列
    enQueue(qu,b);	//根结点指针进入队列
    while (!QueueEmpty(qu) ) {	//队不为空,则循环
   		deQueue(qu,p);			//出队结点p
        printf("%c ", p->data); //访问结点p
        if (p->lchild!=NULL) enQueue(qu,p->lchild);	//有左孩子时将其进队
        if (p->rchild!=NULL) enQueue(qu,p->rchild); //有右孩子时将其进队
    }
}

5.6.4算法的应用

【算法6】:二叉树的建立

20220113172443

20220113172819

Status CreateBiTree(BiTree &T) {
    scanf(&ch); 	//cin> >ch;
    if (ch== “#”) T = NULL;
    else {
    	if (!(T =(BiTNode *)malloc(sizeof(BiTNode))))
    		exit(OVERFLOW);	//T=new BiTNode;
        T->data = ch;	   	//生成根结点
        CreateBiTree(T->lchild);//构造左子树
        CreateBiTree(T->rchild);//构造右子树
    }
    return OK;
}// CreateBiTree

【算法7】:复制二叉树

20220113173950

int Copy(BiTree T,BiTree &NewT){
    if(T==NULL){//如果是空树返回0
    	NewT=NULL;return 0;
    }
    else {
        NewT=new BiTNode;
        NewT->data=T->data;
        Copy(T->lChild,NewT->lchild);
        Copy(T->rChild,NewT->rchild);
    } 
}

【算法8】:计算二叉树深度20220113185653

int Depth( BiTree T){
    if(T==NULL)	  return O;//如果是空树返回0
    else {
   		m=Depth(T->lChild);
        n =Depth(T->rChild);
        if(m>n)   return (m+1);
        else   return(n+1);
    }
}

【算法9】:计算二叉树结点总数

20220113190106

int NodeCount(BiTree T){
    if(T == NULL)
    	return O;
    else
    	return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}

【算法10】:计算二叉树叶子结点总数

20220113190328

int LeadCount(BiTree T){
    if(T==NULL)		//如果是空树返回0
    	return O;
    if (T->lchild == NULL && T->rchild == NULL)
    	return 1;	//如果是叶子结点返回1
    else
    	return LeafCount(T- >lchild) +LeafCount(T->rchild);
    }

5.7线索二叉树

20220114065601

20220114065901

20220114070203

20220114070327

typedef struct BiThrNode{
    int data;
    int Itag, rtag;
    struct BiThrNode *Ichild,rchild;
}BiThrNode,*BiThrTree ;

20220114070624

20220114070932

20220114071017

20220114071137

20220114071435

5.8树和森林

20220114071831

5.8.1双亲表示法

20220114072504

20220114075406

typedef struct PTNode {
    TElemType data;
	int parent;		//双亲位置域
}PTNode;

#define MAX_TREE_SIZE 100
typedef struct {
	PTNode nodes[MAX_TREE_SIZE];
    int r, n;		//根结点的位置和结点个数
}PTree;

5.8.2孩子链表

20220114111213

20220114081026

typedef struct CTNode {
	int child;
	struct CTNode *next;
}*ChildPtr;

typedef struct {
	TElemType	data;
    ChildPtr firstchild;//孩子链表头指针
}CTBox;

typedef struct {
	CTBox nodes[MAX_TREE_SIZE];
    int n, r;//结点数和根结点的位置
}CTree;

5.8.3孩子兄弟表示法

20220114114609

typedef struct CSNode{
	ElemType data;
	struct CSNode *firstchild, *nextsibling;
}CSNode,*CSTree;

20220114115030

5.8.4树与二叉树的转换

20220114115751

20220114115722

20220114120042

20220114120207

20220114120309

20220114120452

5.8.5森林与二叉树的转化

20220114120628

20220114120730

20220114120809

20220114120859

5.8.6树与森林的遍历

20220114121129

20220114121330

先序

20220114121454

中序

20220114121525

20220114121722

5.9哈夫曼树及其应用

5.9.1基本概念

20220114122615

20220114123241

20220114123346

20220114123829

20220114123952

20220114124203

20220114130854

20220114131010

20220114131128

5.9.2构造算法

20220114131310

20220114131501

20220114134614

20220114135318

20220114140702

5.9.3算法实现

20220114141239

20220114144957

20220114204339

typedef struct {
    int weight;
	int parent, lch, rch;
}HTNode,*HuffmanTree;

void CreatHuffmanTree (HuffmanTree HT, int n){//构造哈夫曼树——哈夫曼算法
    if(n<=1)	return;
	m=2*n-1;			//数组共2n-1个元素
	HT=new HTNode[m+1]; //0号单元未用,HT[m]表示根结点
    for(i=1;i<=m;++i){  //将2n-1个元素的lch、rch、parent置为0
		HT[i].Ich=O; HT[i].rch=O; HT[i].parent=O;
	}
	for(i=1;i<=n;++i) cin>>HT[i].weight;//输入前n个元素的weight值
    //初始化结束,下面开始建立哈夫曼树
	for( i=n+1;i<=m; i++){				//合并产生n-1个结点-构造Huffman树
    	Select(HT, i-1,s1, s2);			//在HT[k](1≤k≤i-1)中选择两个其双亲域为0,
    									//且权值最小的结点,并返回它们在HT中的序号s1和s2
    HT[s1].parent=i; HT[s2].parent=i;	//表示从F中删除s1,s2
    HT[i].lch=s1; HT[i].rch=s2 ;
    //s1,s2分别作为i的左右孩子
    HT[i].weight=HT[s1].weight + HT[s2].weight;//i的权值为左右孩子权值之和
    }
}

20220114165721

5.9.4哈夫曼编码

20220114205139

20220114205608

20220114205801

20220114210845

20220114211015

20220114211049

20220114211139

20220114212440

void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n){
    //从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中
    HC=new char *[n+1];		//分配n个字符编码的头指针矢量
    cd=new char [n];		//分配临时存放编码的动态数组空间
    cd[n-1]= ‘1O’;			//编码结束符
    for(i=1; i<=n; ++i){	//逐个字符求哈夫曼编码
        start=n-1; c=i; f=HT[i].parent;
        while(f!=O){		//从叶子结点开始向上回溯,直到根结点
            --start;			//回溯一次start向前指一个位置
            if (HT[f].Ilchild= =c)    cd[start]= '0’ ; //结点c是f的左孩子,则生成代码0
            else	cd[start]= ‘1’ ;	//结点c是f的右孩子,则生成代码1
            c=f; f=HT[f].parent;		//继续向上回溯
        }								//求出第i个字符的编码
        HC[i]= new char [n-start];		//为第i个字符串编码分配空间
        strcpy(HC[i],&cd[start]);		//将求得的编码从临时空间cd复制到HC的当前行中
    }
    delete cd;							//释放临时空间
}// CreatHuffanCode

5.9.5文件的编码和解码

20220114213446

20220114215557

20220114215616

20220114215734

20220114215853

posted @ 2022-01-28 14:10  肖雄_greek  阅读(114)  评论(0)    收藏  举报