数据结构与算法--树

概念:一种数据结构,每个结点有且只有唯一的前驱结点,但可以具有多个后继结点
类别
- (无)有序树
- (完全、满、扩充)二叉树
- 森林
二叉树类别
相关:(父、子、兄弟、叶子、分支、祖先、子孙)结点、边、路径、度、层数、高度

二叉树的抽象数据类型定义(C++):

1. template<class T>  
2. class BinaryTreeNode{   
3.     friend class BinaryTree<T>;  
4.     private:  
5.         T element;                                  //结点的数据域  
6.         BinaryTreeNode<T> * leftChild;                //结点的左孩子指针域  
7.         BinaryTreeNode<T> * rightChild;               //结点的右孩子指针域  
8.     public:  
9.         BinaryTreeNode();  
10.         BinaryTreeNode(const T & ele);  
11.         BinaryTreeNode(const T & ele, BinaryTreeNode<T> * l, BinaryTreeNode<T> * r);  
12.         BinaryTreeNode<T> * getLeftChild() const;  
13.         BinaryTreeNode<T> * getRightChild() const;  
14.         void setLeftChild(BinaryTreeNode<T> * l);  
15.         void setRightChild(BinaryTreeNode<T> * r);  
16.         T getValue() const;  
17.         void setValue(const T & val);  
18.         bool IsLeaf() const;                        //判断该结点是否是叶子结点,若是,则返回true  
19. };  
20.   
21. template<class T>  
22. class BinaryTree{  
23.     private:  
24.         BinaryTreeNode<T> * root;                 //二叉树根结点指针  
25.     public:  
26.         BinaryTree();  
27.         ~BinaryTree();  
28.         bool IsEmpty() const;                       //判断二叉树是否为空树  
29.         BinaryTreeNode<T> * getRoot() const;  
30.         BinaryTreeNode<T> * getParent(BinaryTreeNode<T> * current) const;  
31.         BinaryTreeNode<T> * getLeftSibling(BinaryTreeNode<T> * current) const;  
32.         BinaryTreeNode<T> * getRightSibling(BinaryTreeNode<T> * current) const;  
33.           
34.         void breadthFirstOrder();                   //广度优先遍历  
35.         void preOrder();                            //先序遍历  
36.         void inOrder();                             //中序遍历  
37.         void postOrder();                           //后序遍历  
38.         void levelOrder();                          //层次遍历  
39.         void deleteBianryTree();  
40. };

二叉树的存储
• 顺序存储(完全二叉树,存在空间浪费)
• (三)二叉链表(指针域,存在空间浪费)

二叉树的遍历
• 广度优先遍历(用队列,先从上往下,再从左往右)
• 深度优先遍历(先序、中序、后序[先、中、后指的是根结点的访问顺序,递归定义])
○ 先序遍历(左子树非空||栈非空,将右根压栈)
○ 中序遍历(左子树非空||栈非空,将根压栈)
○ 后序遍历(pre指向上一个访问过的结点,两层循环,将次根压栈)
二叉树的遍历

线索二叉树
• 定义:利用二叉链表的空指针域(n+1个)来存放指向结点在某种遍历次序下的前驱和后继结点的指针
• 线索化(pre指向上一个访问过的结点,先建立前驱线索,再建立后继线索)
线索化二叉树
• 遍历(最左,右)
• [删除]插入[左]右孩子(修改前驱&后继)

二叉搜索树
• 定义:左子树所有结点关键码小于根结点关键码,右子树的大于根结点的
• 查找(二分)&插入(作为叶子结点)
• 删除(子树数目<=1,子树数目==2[合并删除{左子最右下}&复制删除{左子最右下||右子最左下}])
二叉搜索树的删除

平衡二叉树
• 定义:二叉搜索树的一种特殊情况,即每个结点的平衡因子(右子树高度与左子树高度之差)的绝对值不超过1或者是空树
• 查找(同二叉搜索树)
• 插入([左、右]单旋转{回溯取三个结点,折中}、[左右、右左]双旋转{回溯取三个结点,折变直,再变折,左右子树分开})
• 删除(回溯修改平衡因子(失衡则调整),子树高度变化则继续回溯,反之停止)
平衡二叉树的构建


• 定义:[最小]最大堆=完全二叉树+[最小]最大树(每个结点的关键码大于或等于其子结点的关键码)
• 插入(层次最末尾,比较交换)&删除(交换+插入逆过程)
• 构建(筛选法[从第一个分支结点开始调整])
堆的构建

优先队列:堆是一种优先队列,能访问和删除的元素具有最高优先级

Huffman树(最优二叉树)
• 定义:叶子结点带权,带权外部路径长度(根结点到扩充二叉树的外部结点的路径长度)WPL最小
• 构建:合并两根结点权重(子结点权重之和)最小的树,将新树加入集合,删除旧树,直至集合只剩一棵树
• 应用:Huffman编码
Huffman编码

二叉树、树、森林
• 转换 :一一对应(假设树和森林都是有序树,兄弟连心、父子断绝<–>右父重聚、父右断绝)
二叉树、树之间的转换
• 遍历:广度优先遍历、深度优先遍历(先根次序、后根次序)
• 存储:孩子表示法、孩子-兄弟表示法、双亲表示法

#include #include //#define error 0 //#define OVERFLOW -1 //#define ok 1 #define MAXSIZE 100 typedef char TElemType; typedef int Status; typedef struct BiTNode{ //的结点 TElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; typedef BiTree datatype; typedef struct { datatype data[MAXSIZE]; int top; }sqstack; typedef sqstack *STK; Status CreateBiTree(BiTree *T) { //先序二叉树 char ch; ch=getchar(); if(ch=='#') (*T)=NULL; //#代表空 else { (*T)=(BiTree)malloc(sizeof(BiTNode)); (*T)->data=ch; CreateBiTree(&(*T)->lchild); //先序立左子 CreateBiTree(&(*T)->rchild); //先序立右子 } return 1; } STK initstack() //栈的初始化 { STK s; s=(STK)malloc(MAXSIZE*sizeof(sqstack)); s->top=0; return s; //返回指向栈地址的指针 } Status stackempty(STK s) //判断栈是否为空 { return(s->top==0); } Status push(STK s,datatype *e) //压栈函数 { if(s->top==MAXSIZE) //栈满,则返回错误 return 0; else { s->data[s->top]=*e; (s->top)++; return 1; } } Status pop(STK s,datatype *e) //出栈函数 { if(stackempty(s)) //判断栈是否为空 return 0; else { s->top--; *e=s->data[s->top]; //用e接受栈顶元素 return 1; } } Status inordertraverse(BiTree T) //中序非递归遍历二叉树 { STK s; s=initstack(); // BiTree T; BiTree p; p=T; while (p||!stackempty(s)) { if(p) { push(s,&p); p=p->lchild; } else { pop(s,&p); printf("%2c",p->data); p=p->rchild; }//else }//while return 1; }//inordertraverse void main() { BiTree T=NULL; printf("\n Creat a Binary Tree .\n"); //立一棵二叉树T* CreateBiTree( &T ); printf ("\nThe preorder is:\n"); inordertraverse(T); }
顺序存储的线性表 时数 2 性质 验证 内容:1、设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。试设计一算法,将x插入到线性表的适当位置上,以保持线性表的有序性。 2、用向量作存储结构,试设计一个算法,仅用一个辅助结点,实现将线性表中的结点循环右移k位的运算。 3、用向量作存储结构,试设计一个算法,仅用一个辅助结点,实现将线性表逆置的运算。 要求:了解线性表的逻辑结构特征,熟练掌握线性表的顺序存储结构的描述方法,及在其上实现各种基本运算的方法。 单链表上的操作 时数 2 性质 验证 内容:1、已知带头结点的动态单链表L中的结点是按整数值递增排序的,试写一算法将值为x的结点插入到表L中,使L仍然有序。 2、设计一算法,逆置带头结点的动态链表L。要求利用原表的结点空间,并要求用尽可能少的时间完成。 3、假设有两个按元素值递增有序的线性表A和B,均以单链表作存储结构,试编写算法将A表和B表归并成一个按元素值递减有序的线性表C,并要求利用原表的空间存放C。 要求:熟练掌握线性表的单链式链接存储结构及在其上实现线性表的各种基本运算的方法。 循环链表和双链表 时数 2 性质 验证 内容:1、假设在长度大于1的单循环链表中,既无头结点也无头指针。s为指向某个结点的指针,试编写算法删除结点*s的直接前驱结点。 2、已知由单链表表示的线性表中,含有三类字符的数据元素(如:字母、数字和其它字符),设计算法构造三个以循环链表示的线性表,使每一个表中只含同一类的字符,且利用原表中的结点空间作为这三个表的空间。(头结点可以另辟空间) 3、有一双链表,每个结点中除有prior、data和next域外,还有一访问频度域freq,在链表被启用前,其值均初始化为零。每当在链表上进行一次LOCATE(L,x)运算,元素值为x的结点中freq域的值增1,并使此链表中结点保持按freq递减的顺序排列,以便使频繁访问的结点总是靠近表头。设计满足上述要求的LOCATE算法。 要求:熟练掌握线性表的循环链式和双链式链接存储结构及在其上实现线性表的各种基本运算的方法。 栈和队列 时数 2 性质 验证 内容:1、设单链表中存放着n个字符,设计算法,判断该字符串中是否有中心对称关系。例如:xyzzyx、xyzyx都算是中心对称的字符串。 2、设计算法判断一个算术表达式的圆括号是否配对。(提示:对表达式进行扫描,遇‘(’进栈,遇‘)’退掉栈顶的‘(’,表达式被扫描完毕,栈为空) 3、假设以带头结点的循环链表表示队列,并只设一个指针指向队尾,编写相应的置队空、入队和出队算法。 要求:掌握栈和队列的数据结构的特点;熟练掌握在两种存储结构上实现栈和队列的基本运算;学会利用栈和队列解决一些实际问题。 串运算的实现 时数 2 性质 验证 内容:1、若X和Y是用结点大小为1的单链表表示的串,设计算法找出X中第一个不在Y中出现的字符。 2、设计一算法,在顺序串上实现串的比较运算strcmp(S,T)。 3、若S和T是用结点大小为1的单链表存储的两个串,设计算法将S中首次与T匹配的子串逆置。 要求:熟练掌握串的顺序和链接存储结构的实现方法;熟练掌握在两种存储结构上实现串的各种运算。 的应用 时数 2 性质 验证 内容:1、以二叉链表作存储结构,设计求二叉树高度的算法。 2、一棵n个结点的完全二叉树用向量作存储结构,用非递归算法实现对该二叉树进行前序遍历。 3、以二叉链表作存储结构,编写非递归的前序、中序、后序遍历算法。 要求:熟悉二叉树的各种存储结构的特点及适用范围;掌握二叉树的存储结构的方法;熟练掌握二叉树的前序、中序、后序遍历的递归及非递归算法;灵活运用递归的遍历算法实现二叉树的其它各种运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值