二叉树的操作

二叉树特点:非线性

#include"Bitree.h"
#ifndef _STACK_H_
#define _STACK_H_
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef BiTree ElemType;
typedef struct
{
 ElemType *base;
 ElemType *top;
 int stacksize;
}SqStack;
Status InitStack(SqStack &S);
Status DestroyStack(SqStack &S);
Status ClearStack(SqStack &S);
Status StackEmpty(SqStack S);
Status Push(SqStack &S, ElemType e);
Status Pop(SqStack &S, ElemType &e);
#endif

#include"Bitree.h"
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef BiTree ElemType;
typedef struct QNode
{
 ElemType data;
 struct QNode *next;
}QNode, *Queueprt;
typedef struct
{
 Queueprt front;//队头指针
 Queueprt rear;//队尾指针
}LinkQueue;
Status InitQueue(LinkQueue &Q);
Status DestoryQueue(LinkQueue &Q);
Status ClearQueue(LinkQueue &Q);
Status EmptyQueue(LinkQueue &Q);
Status EnterQueue(LinkQueue &Q, ElemType e);
Status DelecetQueue(LinkQueue &Q, ElemType &e);
#endif

#ifndef _BITREE_H_
#define _BITREE_H_
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW_s -2
typedef int Status;
typedef char TElemType;
typedef struct BiTNode
{
 TElemType data;
 struct  BiTNode *lchild, *rchild;
} BiTNode,*BiTree;

Status CreateBiTree(BiTree &T);
Status DestroyBiTree(BiTree &T);
Status BiTreeDepth(BiTree T);
Status countleaf(BiTree T);
Status count_n(BiTree T);
Status single_point(BiTree T);
Status double_point(BiTree T);
Status FindPoint(BiTree T, TElemType e);
void change_left_right(BiTree T);
void PreOrderTraverse(BiTree T);
void InOrderTraverse(BiTree T);
void NextOrderTraverse(BiTree T);
void LevelOrder(BiTree T);
void U_InOrderTraverse(BiTree T);
#endif

#include"stack.h"
#include"Bitree.h"
#include<iostream>
using namespace std;
//构造空栈
Status InitStack(SqStack &S)
{
 S.base = (ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));
 if (!S.base)
 {
  return OVERFLOW;
 }
 else
 {
  S.top = S.base;
  S.stacksize = STACK_INIT_SIZE;
  return OK;
 }
}
//销毁栈
Status DestroyStack(SqStack &S)
{
 ElemType e;
 if (S.top != S.base)
 {
  Pop(S, e);
 }
 return OK;
}
//清空栈
Status ClearStack(SqStack &S)
{
 if (S.top != S.base)
 {
  S.top = S.base;
 }
 return OK;
}
//置空栈
Status StackEmpty(SqStack S)
{
 if (S.top == S.base)
 {
  return OK;
 }
 else
 {
  return ERROR;
 }
}
//入栈
Status Push(SqStack &S, ElemType e)
{
 if (S.top - S.base >= S.stacksize)
 {
  S.base = (ElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT)*sizeof(ElemType));
  if (!S.base)
  {
   return OVERFLOW;
  }
  else
  {
   S.top = S.base + S.stacksize;
   S.stacksize += STACKINCREMENT;
  }
 }
 else
 {
  *S.top++ = e;
  return OK;
 }
}
//出栈
Status Pop(SqStack &S, ElemType &e)
{
 if (S.top == S.base)
 {
  return ERROR;
 }
 else
 {
  e = *--S.top;
  return OK;
 }
}

#include"Queue.h"
#include"Bitree.h"
#include<iostream>
using namespace std;
//构造空队列
Status InitQueue(LinkQueue &Q)
{
 Q.rear = Q.front = (Queueprt)malloc(sizeof(QNode));
 if (!Q.front)
 {
  return OVERFLOW;
 }
 else
 {
  Q.front->next = NULL;
  return OK;
 }
}
//销毁队列
Status DestoryQueue(LinkQueue &Q)
{
 while (Q.front)
 {
  Q.rear = Q.front->next;
  free(Q.front);
  Q.front = Q.rear;
 }
 return OK;
}
//清空队列
Status ClearQueue(LinkQueue &Q)
{
 Q.rear = Q.front;
 return OK;
}
//置空队列
Status EmptyQueue(LinkQueue &Q)
{
 if (Q.rear == Q.front)
 {
  return TRUE;
 }
 else
 {
  return ERROR;
 }
}
//入队
Status EnterQueue(LinkQueue &Q, ElemType e)
{
 Queueprt p;
 p = (Queueprt)malloc(sizeof(QNode));
 if (!p)
 {
  return OVERFLOW;
 }
 else
 {
  p->data = e;
  p->next = NULL;
  Q.rear->next = p;
  Q.rear = p;
  return OK;
 }
}
//出队
Status DelecetQueue(LinkQueue &Q, ElemType &e)
{
 Queueprt p;
 p = Q.front->next;
 if (Q.rear == Q.front)
 {
  return ERROR;
 }
 else
 {
  e = p->data;
  Q.front->next = p->next;
  if (Q.rear == p)
  {
   Q.rear = Q.front;
  }
  free(p);
  return OK;
 }
}

#include"Bitree.h"
#include"Queue.h"
#include"Stack.h"
#include<iostream>
using namespace std;
//构造二叉树
Status CreateBiTree(BiTree &T)
{
 char ch;
 ch = getchar();
 if (ch == '#')
 {
  T = NULL;
 }
 else
 {
  if (!(T = (BiTNode*)malloc(sizeof(BiTNode))))
  {
   exit(OVERFLOW_s);
  }
  else
  {
   T->data = ch;
   CreateBiTree(T->lchild);
   CreateBiTree(T->rchild);
  }
 }
 return OK;
}
//销毁二叉树
Status DestroyBiTree(BiTree &T)
{
 if (T)
 {
  DestroyBiTree(T->lchild);
  DestroyBiTree(T->rchild);
  free(T);
  T = NULL;
 }
 return OK;
}
//求二叉树的深度
Status BiTreeDepth(BiTree T)
{
 int depth,depthleft,depthright;
 if (!T)
 {
  depth = 0;
 }
 else
 {
  depthleft = BiTreeDepth(T->lchild);
  depthright = BiTreeDepth(T->rchild);
  depth = 1 + (depthleft > depthright ? depthleft : depthright);
 }
 return depth;
}
//求叶子节点数
Status countleaf(BiTree T)
{
 int  num,num1,num2;
 if (!T)
 {
  num = 0;
 }
 else
 {
  if (T->lchild == NULL&&T->rchild == NULL)
  {
   num = 1;
  }
  else
  {
   num1 = countleaf(T->lchild);
   num2 =   countleaf(T->rchild);
   num = num1 + num2;
  }
 }
 return num;
}
//求总结点数
Status count_n(BiTree T)
{
 int num1, num2, num;
 if (!T)
 {
  num = 0;
 }
 else if (T->lchild == NULL&&T->rchild == NULL)
 {
  num = 1;
 }
 else
 {
  num1 = count_n(T->lchild);
  num2 = count_n(T->rchild);
  num = num1 + num2+1;
 }
 return num;
}
//求单分支结点个数
Status single_point(BiTree T)
{
 int  num;
 if (!T)
 {
  num = 0;
 }
 else
 {
  if (T->lchild == NULL&&T->rchild == NULL)
  {
   num = 0;
  }
  else
  {
   if (T->lchild == NULL||T->rchild == NULL)
   {
    if (T->lchild != NULL && T->rchild == NULL)
    {
     num= single_point(T->lchild) + 1;
    }
    else
    {
     num= single_point(T->rchild) + 1;
    }
   }
   else
   {
    num= single_point(T->lchild) + single_point(T->rchild);
   }
  }
 }
 return num;
}
//求双分支结点的个数
Status double_point(BiTree T)
{
 int num1,num2,num;
 if (!T)
 {
  num = 0;
 }
 else
 {
  if (T->lchild == NULL&&T->rchild == NULL)
  {
   num = 0;
  }
  else
  {
   num1 = double_point(T->lchild);
   num2 = double_point(T->rchild);
   if (T->lchild != NULL&&T->rchild != NULL)
   {
    num = num1 + num2 + 1;
   }
   else
   {
    num = num1 + num2;
   }
  }
 }
 return num;
}
//查找某个结点
Status FindPoint(BiTree T, TElemType ch)
{
 if (!T)
 {
  return ERROR;
 }
 else
 {
  if (T->data == ch)
  {
   return OK;
  }
  else
  {
   if (FindPoint(T->lchild, ch) || FindPoint(T->rchild, ch))
   {
    return OK;
   }
   else
   {
    return ERROR;
   }
  }
 }
}
//交换左右子树
void change_left_right(BiTree T)
{
 BiTree temp;
 if (T)
 {
  change_left_right(T->lchild);
  change_left_right(T->rchild);
  temp = T->lchild;
  T->lchild = T->rchild;
  T->rchild = temp;
 }
}
//前序遍历
void PreOrderTraverse(BiTree T)
{
 if (T)
 {
  cout << T->data << " ";
  PreOrderTraverse(T->lchild);
  PreOrderTraverse(T->rchild);
 }
}
//中序遍历
void InOrderTraverse(BiTree T)
{
 if (T)
 {
  InOrderTraverse(T->lchild);
  cout << T->data << " ";
  InOrderTraverse(T->rchild);
 }
}
//后序遍历
void NextOrderTraverse(BiTree T)
{
 if (T)
 {
  NextOrderTraverse(T->lchild);
  NextOrderTraverse(T->rchild);
  cout << T->data << " ";
 }
}
//按层次遍历
void LevelOrder(BiTree T)
{
 LinkQueue Q;
 ElemType p;
 InitQueue(Q);
 if (T)
 {
  EnterQueue(Q, T);
  while (!EmptyQueue(Q))
  {
   DelecetQueue(Q, p);
   cout << p->data<<" ";
   if (p->lchild != NULL)
   {
    EnterQueue(Q, p->lchild);
   }
   if (p->rchild != NULL)
   {
    EnterQueue(Q, p->rchild);
   }
  }
 }
}
//非递归中序遍历
void U_InOrderTraverse(BiTree T)
{
 SqStack S;
 InitStack(S);
 ElemType p = T;
 while (p || !StackEmpty(S))
 {
  if (p)
  {
   Push(S, p);
   p = p->lchild;
  }
  else
  {
   Pop(S, p);
   cout << p->data<<" ";
   p = p->rchild;
  }
 }
}


#include"Bitree.h"
#include<iostream>
using namespace std;
int main()
{
 BiTree T,f=NULL,p,q,s;
 TElemType ch;
 int select,num;
 CreateBiTree(T);
 do
 {
  cout << "1.求二叉树的深度!"<<endl;
  cout << "2.求叶子节点数!"<<endl;
  cout << "3.求总结点数!" << endl;
  cout << "4.求单分支结点个数!" << endl;
  cout << "5.求双分支结点的个数" << endl;
  cout << "6.查找某个结点" << endl;
  cout << "7.交换左右子树" << endl;
  cout << "8.前序遍历" << endl;
  cout << "9.中序遍历" << endl;
  cout << "10.后序遍历" << endl;
  cout << "11.按层遍历!" << endl;
  cout << "12.非递归中序遍历!" << endl;
  cout << "13.操作结束!" << endl;
  cout << "请选择:" << endl;
  cin >> select;
  switch (select)
  {
  case 1:
   cout << "二叉树的深度为:" << BiTreeDepth(T) << endl;
   break;
  case 2:
   cout << "叶子结点的个数为:" << countleaf(T) << endl;
   break;
  case 3:
   cout << "总结点数为:" << count_n(T) << endl;
   break;
  case 4:
   cout << "单分支结点的个数为:" << single_point(T) << endl;
   break;
  case 5:
   cout << "双分支结点的个数为:" << double_point(T) << endl;
   break;
  case 6:
   cout << "请输入结点:" << endl;
   cin >> ch;
   if (FindPoint(T, ch) == ERROR)
   {
    cout << "二叉树为空或未找到!" << endl;
   }
   else
   {
    cout << "找到了!" << endl;
   }
   break;
  case 7:
   change_left_right(T);
   break;
  case 8:
   PreOrderTraverse(T);
   cout << endl;
   break;
  case 9:
   InOrderTraverse(T);
   cout << endl;
   break;
  case 10:
   NextOrderTraverse(T);
   cout << endl;
   break;
  case 11:
   LevelOrder(T);
   cout << endl;
   break;
  case 12:
   U_InOrderTraverse(T);
   cout << endl;
   break;
  case 13:
   cout << "操作结束!" << endl;
   break;
  default:
   cout << "输入错误!" << endl;
  }
 } while (select != 13);
 DestroyBiTree(T);//end of Bitree
 return 0;
}

<think>首先,用户的问题是关于二叉树操作,他们问:“我想了解二叉树操作的相关知识 请问二叉树操作有哪些”。这基于他们提供的引用内容,包括引用[1]、[2]和[3],这些是关于二叉树的基本操作、定义和数据结构。 从系统指令中,我需要: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,逐步解决问题。 - 尽量保证回答真实可靠。 参考用户提供的引用: - 引用[1]提到了二叉树的基本操作,如遍历、高度计算、查找节点等。 - 引用[2]列出了实验内容,包括二叉树的建立、遍历、深度计算、结点计数等。 - 引用[3]定义了二叉树的结构。 用户上一次的问题和我的回答:用户的上一次问题是系统级的指令示例,没有实际的对话历史。所以,我需要基于当前查询。 核心问题:用户想知道二叉树操作的种类。我需要提供一个清晰、结构化的回答,涵盖常见的二叉树操作。 主要二叉树操作包括: 1. **创建二叉树**:如初始化一个二叉树。 2. **遍历**: - 前序遍历(Pre-order):根 -> 左 -> 右 - 中序遍历(In-order):左 -> 根 -> 右 - 后序遍历(Post-order):左 -> 右 -> 根 - 层次遍历(Level-order):按层遍历 3. **查询操作**: - 计算高度/深度 - 计算结点个数 - 计算叶子结点个数 - 计算度为1的结点个数 - 查找特定值的结点 4. **修改操作**: - 插入结点 - 删除结点 - 交换左右孩子 5. **其他操作**: - 复制二叉树 - 比较二叉树是否相同 - 输出路径(如从叶子到根的路径) 从引用中: - 引用[1]提到了遍历、高度计算、查找。 - 引用[2]详细列出了操作:建立二叉树、各种遍历、深度计算、结点统计、叶子统计、度为1的结点统计、输出路径、交换孩子、双序遍历等。 我需要结构化回答: 1. **介绍**:简要定义二叉树和相关操作。 2. **详细列出操作**:分组或列举常见操作。 3. **解释关键操作**:简要解释一些重要操作,如遍历。 4. **生成相关问题**:在末尾添加相关问题。 使用中文回答。 数学表达式:二叉树操作主要是算法性的,可能不需要太多数学,但如果有,如高度计算,可以用行内格式。例如,高度计算的递归公式:$height(node) = 1 + \max(height(left), height(right))$ if node not null, else 0。 引用标识:在回答中,如果我参考了提供的引用,需要在段落末尾添加[^1], [^2], [^3]。例如,基于引用[1]和[2]。 回答结构: - 开头:确认用户问题,介绍二叉树操作。 - 主体:分类列出和解释操作。 - 结尾:生成相关问题。 相关问题:基于系统指令,需要生成相关问题。示例中是针对快速排序的,所以我应该为二叉树操作生成相关问题。 相关问题想法: 1. 二叉树的遍历算法如何实现? 2. 如何优化二叉树的查找操作? 3. 二叉树在哪些实际应用中常用? 4. 二叉树的高度和结点个数有什么关系? 完整回答大纲: 1. 二叉树的定义(基于引用[3])。 2. 主要操作类别: - 遍历操作 - 查询操作 - 修改操作 - 特殊操作 3. 详细描述每个操作,引用来源。 4. 生成相关问题。 </think>### 二叉树的基本操作详解 二叉树是一种树形数据结构,每个节点最多有两个子节点(左子节点和右子节点),常用于实现高效的数据检索和排序算法。基于您提供的引用内容,我将系统性地介绍二叉树的主要操作类别及其关键功能。这些操作包括创建、遍历、查询和修改二叉树,确保数据结构的完整性和效率。以下是核心操作的分类说明,引用自相关资料[^1][^2][^3]。 #### 1. **二叉树的创建与初始化** - **建立二叉树**:通过递归或非递归方法初始化一棵二叉树。例如,使用二叉链表表示法动态构建树结构(算法5.3)[^2]。 - 步骤:从根节点开始,递归创建左子树和右子树。 - **复制二叉树**:完整复制一棵二叉树的结构和数据,常用于备份或无副作用的操作。 #### 2. **二叉树的遍历操作** 遍历是访问二叉树所有节点的基本方式,分为递归和非递归实现: - **前序遍历(Pre-order)**:先访问根节点,再遍历左子树,最后遍历右子树。顺序:根 → 左 → 右。常用于表达树的结构(如序列化)[^1][^2]。 - 示例代码片段: ```c void PreOrderTraverse(BTNode* root) { if (root != NULL) { printf("%d ", root->data); // 访问根节点 PreOrderTraverse(root->left); // 递归左子树 PreOrderTraverse(root->right); // 递归右子树 } } ``` - **中序遍历(In-order)**:先遍历左子树,再访问根节点,最后遍历右子树。顺序:左 → 根 → 右。常用于二叉搜索树(BST)的输出有序序列(算法5.1)[^2]。 - **后序遍历(Post-order)**:先遍历左子树,再遍历右子树,最后访问根节点。顺序:左 → 右 → 根。常用于释放树的内存或计算表达式树[^1][^2]。 - **层次遍历(Level-order)**:按层从上到下、从左到右访问节点。通常借助队列实现,适用于广度优先搜索(BFS)[^1]。 - **特殊遍历**:如双序遍历(DblOrderTraverse),每个节点被访问两次(根 → 左子树 → 根 → 右子树),用于特定算法设计[^2]。 #### 3. **二叉树的查询与统计操作** 这些操作用于获取二叉树的属性信息,通常通过递归算法实现: - **计算高度(深度)**:返回树的最大深度。递归公式为:$height(node) = \begin{cases} 0 & \text{if node is NULL} \\ 1 + \max(height(\text{left}), height(\text{right})) & \text{otherwise} \end{cases}$。引用[^1]中的示例代码: ```c int BinaryTreeHeight(BTNode* root) { if (root == NULL) return 0; int left = BinaryTreeHeight(root->left); int right = BinaryTreeHeight(root->right); return (left > right ? left : right) + 1; // 取较大值加1 } ``` - **统计结点个数**:递归计算树中所有节点的总数,包括根节点和子树节点(算法5.6)[^2]。 - 公式:$count(node) = \begin{cases} 0 & \text{if node is NULL} \\ 1 + count(\text{left}) + count(\text{right}) & \text{otherwise} \end{cases}$。 - **统计叶子结点个数**:仅计算没有子节点的节点数。叶子节点条件是:$left == \text{NULL} \land right == \text{NULL}$[^2]。 - **统计度为1的结点个数**:计算只有一个子节点的节点数。度为1的条件是:$(left == \text{NULL} \land right \neq \text{NULL}) \lor (left \neq \text{NULL} \land right == \text{NULL})$[^2]。 - **查找值为x的结点**:在树中搜索指定值的节点,返回其位置。递归遍历所有节点,比较数据值[^1]。 - **输出路径**:如从每个叶子节点到根节点的路径,用于调试或路径分析[^2]。 #### 4. **二叉树的修改操作** 这些操作改变树的结构或内容: - **插入结点**:在指定位置添加新节点(如BST中按值插入),可能涉及树重构。 - **删除结点**:移除指定节点并调整子树以维持树的性质(如BST的删除算法)。 - **交换左右孩子**:反转节点的左子树和右子树,用于镜像树的操作[^2]。 - 示例:递归交换每个节点的左子和右子。 - **销毁二叉树**:释放所有节点内存,避免内存泄漏。 #### 5. **其他高级操作** - **比较二叉树**:检查两棵树是否完全相同(结构和数据)。 - **序列化与反序列化**:将树转换为字符串存储,或从字符串重建树。 - **优化操作**:如平衡二叉树(AVL树或红黑树)的旋转操作,确保高效查询。 这些操作覆盖了二叉树的常见应用场景,如数据库索引、编译器设计和文件系统管理。实现时需注意递归效率(可能栈溢出)和空间复杂度($O(n)$平均情况),实际编码可参考引用[^1][^2]中的算法示例[^1][^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值