树、二叉树、查找

树的定义

树结构(Tree)是 n(n ≥ 0) 个结点的有限集,当 n = 0 时为空树,否则为非空树。对于非空树有如下特点:
1.有且仅有一个特定的根结点,不允许存在多个结点;
2。除根结点以外的其余结点可分为 m(m > 0) 个互不相交的有限集,其中每一个有限集本身还是一棵树,称为根的子树。子树的个数没有限制,但是一定不能有交集。

树的类型定义:
ADT Tree{
数据对象:D是具有相同特性的数据元素的集合。数据关系:若D为空集,则称为空树;否则:(1)在D中存在唯一的称为根的数据元素root,(2)当n>1时,其余结点可分为m (m>0)个互不相交的有限集T1,T2,…, Tm,其中每一棵子集本身又是一棵符合本定义的树,称为根root的子树。基本操作:
■查找类■插入删除ADT Tree

树的基本功能

插入:
InitTree(&T)//初始化置空树
CreateTree(&T, definition)//按定义构造Assign(T, cur_e, value)//给当前结点赋值InsertChild(&T,&p, i, c)//将以c为根的树插入为结点p的第i棵子树

删除:
ClearTree(&T)//将树清空
DestroyTree(&T)//销毁树的结构
DeleteChild(&T,&p,i)//删除结点p的第i个孩子

查找:
Root(T)
//求树的根结点
Value(T, cur_e)//求当前结点的元素值
Parent(T, cur_e)//求当前结点的双亲结点
LeftChild(T, cur_e)//求当前结点的最左孩子
RightSibling(T, cur_e)//求当前结点的右兄弟
TreeEmpty(T)//判定树是否为空树
TreeDepth(T)//求树的深度
遍历
TraverseTree( T)//遍历

树的基本术语

** 结点: **包含一个数据元素及若干指向其子树的分支。
**结点的度:**结点拥有的子树数。
**叶子(或终端)结点:**度为零的结点。
**分支(或非终端)结点:**度大于零的结点。
**树的度:**树中所有结点的度的最大值。
结点的子树的根称为该结点的孩子(child)。相应的,该结点称为孩子的双亲(parent)。
同一个双亲的孩子之间互称兄弟。
**结点的层次:**根结点的层次为1,第l层的结点的子树的根结点的层次为L+1。
双亲在同一层的结点互为堂兄弟。
**树的深度:**树中叶子结点所在的最大层次。
**森林:**是m(m>0)棵互不相交的树的集合。
**有序树:**子树之间存在确定的次序关系(树中结点的各子树从左到右是有次序的,即不能互换)。
**无序树:**子树之间不存在确定的次序关系。树型结构和线性结构的特点:

二叉树在这里插入图片描述

二叉树的定义

n(n>=0)个结点的有限集合,它或为空树(n=0),或由一个根结点和至多两棵称为根的左子树和右子树的互不相交的二叉树组成。.
注:二叉树中不存在度大于2的结点,并且二叉树的子树有左子树和右子树之分。

二叉树的性质

性质1︰在二叉树的第i层上至多有2i-1个结点(i≥1)。
性质2:深度为k的二叉树上至多含2k-1个结点(k≥1)。
性质3:对任何一棵二叉树,若它含有ne个叶子结点、n2个度为2的结点,则必存在关系式:no =n2+1。

特殊二叉树

满二叉树:指的是深度为k且含有2k-1个结点的二叉树。

完全二叉树:树中所含的n个结点和满二叉树中编号为1至n的结点一一对应。

共同特点:
特点:
⑴叶子结点只可能在层次最大的两层出现;
⑵对任一结点,若其右分支下的子孙的最大层次为L,则其左分支下的子孙的最大层次为l或L+1。
满二叉树特点:
特点:是每一层上的结点数都是最大结点数。

完全二叉树的性质:

性质4∶具有n个结点的完全二叉树的深度为
LLog,n_|+1。
性质5:若对含n个结点的完全二叉树从上到下且从左至右进行1至n的编号,则对完全二叉树中任意-个编号为i的结点:
(1)若i=1,则该结点是二叉树的根,无双亲,否则,编号为i/2的结点为其双亲结点;
(2)若2i>n,则该结点无左孩子,否则,编号为2i的结点为其左孩子结点;
(3)若2i+1>n,则该结点无右孩子结点,否则,编号为2i+1的结点为其右孩子结点

二叉树的遍历

遍历分为:
先(根)序的遍历、中(根)序的遍历、后(根)序的遍历。
以中序遍历为例:
递归描述

void Inorder (BiTree T){//中序遍历二叉树
if(T){
Inorder(T->lchild);//遍历左子树
cout<<T->data;//访问结点
Inorder(T->rchild);//遍历右子树}
}

非递归算法描述

void InorderTraverse(BiTree T){
Initstack(S); p = T;
声明q;//存放栈顶弹出元素while (p l / ! stackEmpty(S)){
if (p){
push(s, p);p = p->lchild;}else{
Pop(s, q);
cout << q->data;p = q->rchild;}
}
}

二叉树的运用例题

一、表达式树
在这里插入图片描述
函数接口定义:

void InitExpTree(BTree &T,string str) ; //建表达式的二叉树
double EvaluateExTree(BTree T);//计算表达式树

T:二叉树 str:输入的表达式

裁判测试程序样例:



#include<iostream>
#include<string>
#include<stack>
using namespace std;
typedef struct BiTNode{                             //二叉树的二叉链表存储表示
    char data;
    struct BiTNode *lchild,*rchild;
}BTNode,*BTree;
void InitExpTree(BTree &T,string str) ; //建二叉表达式树 
double EvaluateExTree(BTree T);//计算表达式树 
char Precede(char t1,char t2) ;//比较t1,t2运算符优先级函数 
int In(char c) ;//判断c是否运算符 
void CreateExpTree(BTree &T,BTree a,BTree b,char ch);//建简单二叉树 
void DestroyBTree(BTree bt);//销毁树 
int main() 
 {
   string str;
   BTree T;
   getline(cin,str);
   InitExpTree(T,str);          //创建表达式树
   cout<<EvaluateExTree(T);             //输出值
   DestroyBTree(T);
   return 0;
 }
char Precede(char t1,char t2) 
 { /*判断两符号的优先关系 */
    char f;
    switch(t2)
    {
        case '+': if(t1=='('||t1=='#')  f='<';
                  else  f='>';
                  break;
        case '-': if(t1=='('||t1=='#')  f='<';
                  else  f='>';
                  break;
        case '*':if(t1=='*'||t1=='/'||t1==')') f='>';
                 else f='<';
                 break;
    case '/':if(t1=='*'||t1=='/'||t1==')') f='>';
                     else  f='<';
                     break;
        case '(': if(t1!=')')  f='<';
                    break;
        case')': if(t1=='(') f='=';
        else f='>';
           break;
    case'#':  if(t1=='#') f='=';
             else f='>';
   }
    return f;
 }
int In(char c) 
 { /* 判断c是否为运算符 */
   switch(c)
   {
      case '+':
      case'-':
      case'*':
      case '/':
      case'#':
      case '(':
      case')':return 1;break;
      default:return 0;
   }
 }
void CreateExpTree(BTree &T,BTree a,BTree b,char ch)
{           //简单二叉树的创建
    T=new BTNode;
    T->data=ch;
    T->lchild=a;
    T->rchild=b;
}
void DestroyBTree(BTree bt)//销毁树
{
    if(bt!=NULL)
    {
      DestroyBTree(bt->lchild);
      DestroyBTree(bt->rchild);
      delete bt;    
    }
}
/* 请在这里填写答案 */

输入样例:

1+2*3

输出样例:

7
void InitExpTree(BTree &T,string str) 
{
   stack <BTree> forest;
   stack <char>op ;
   BTree a_node;
    BTree num1,num2;
    int i = 0;
    while(str[i]!='\0')
    {
        if(In(str[i]))
        {
            if(op.empty()||Precede(op.top(),str[i])=='<')
               {
                   op.push(str[i++]);
               }
               else if (Precede(op.top(),str[i])=='>')  
               {
                   num2 = forest.top();
                   forest.pop();
                   num1 = forest.top();
                   forest.pop();
                   CreateExpTree(a_node,num1,num2,op.top());
                   op.pop();
                   forest.push(a_node);
               }
               else
               {
                   op.pop();
                   i++;
               }
        }
        else
               {
                  CreateExpTree(a_node,NULL,NULL,str[i++]);
                  forest.push(a_node);
               }
    }
    while(!op.empty())
               {
                   num2 = forest.top();
                   forest.pop();
                   num1 = forest.top();
                   forest.pop();
                   CreateExpTree(a_node,num1,num2,op.top());
                   op.pop();
                   forest.push(a_node);
               }
                T = forest.top();
               }
    //建表达式的二叉树
double EvaluateExTree(BTree T)
               {
                   double num1,num2;
                   if(!In(T->data))
                   {
                    return T->data-'0';
                   }
                   num1 = EvaluateExTree(T->lchild);
                   num2 = EvaluateExTree(T->rchild);
                   switch (T->data)
                   {
                       case '+':
                           return num1+num2;
                       case '-':
                           return num1 - num2;
                       case '*':
                           return num1*num2;
                       case '/':
                           if(num2 ==0)
                           {
                               cout<<"divide 0 error!";
                               exit(0);
                           }

                               return num1/num2;

                           
                   }
               }//计算表达式树

结果

在这里插入图片描述

目录树

目录树(https://www.cnblogs.com/linfangnan/p/12617499.html#%E6%89%93%E5%8D%B0%E7%9B%AE%E5%BD%95%E6%A0%91)

查找

在这里插入图片描述

HASH 链与“航空公司VIP客户查询”题解

思考

1树都是二叉树吗?
2.二叉树结构有什么优势?
3.哈夫曼树和AVL树的区别?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值