二叉树基本操作经典实例

合集下载

C语言之二叉树各种操作

C语言之二叉树各种操作

用函数实现如下二叉排序树算法:(1)插入新结点(2)前序、中序、后序遍历二叉树(3)中序遍历的非递归算法(4)层次遍历二叉树(5)在二叉树中查找给定关键字(函数返回值为成功1,失败0)(6)交换各结点的左右子树(7)求二叉树的深度(8)叶子结点数Input第一行:准备建树的结点个数n第二行:输入n个整数,用空格分隔第三行:输入待查找的关键字第四行:输入待查找的关键字第五行:输入待插入的关键字Output第一行:二叉树的先序遍历序列第二行:二叉树的中序遍历序列第三行:二叉树的后序遍历序列第四行:查找结果第五行:查找结果第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列第九行:插入新结点后的二叉树的中序遍历序列(非递归算法)第十行:插入新结点后的二叉树的层次遍历序列第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列第十七行:二叉树的深度第十八行:叶子结点数7↙40 20 60 18 50 56 90↙18↙35↙30↙Sample Output40 20 18 60 50 56 9018 20 40 50 56 60 9018 20 56 50 90 60 40140 20 18 30 60 50 56 9018 20 30 40 50 56 60 9018 30 20 56 50 90 60 4018 20 30 40 50 56 60 9040 20 60 18 30 50 90 5640 60 90 50 56 20 30 1890 60 56 50 40 30 20 1890 56 50 60 30 18 20 4040 20 18 30 60 50 56 9018 20 30 40 50 56 60 9018 30 20 56 50 90 60 4044#include "stdio.h"#include "malloc.h"#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2#define MAXQSIZE 100typedef int Status;#define STACK_INIT_SIZE 10#define STACKINCREMENT 2typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;//左右孩子指针} BiTNode,*BiTree;typedef BiTree SElemType;typedef BiTree QElemType;typedef struct QNode{QElemType num;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;struct SqStack{SElemType *base; // 在栈构造之前和销毁之后,base的值为NULLSElemType *top; // 栈顶指针int stacksize; // 当前已分配的存储空间,以元素为单位}; // 顺序栈Status InitStack(SqStack &S) // 构造一个空栈S{S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!S.base){return ERROR;}S.top = S.base;S.stacksize=STACK_INIT_SIZE;return OK;}Status Push(SqStack &S,SElemType e) // 在栈S中插入元素e为新的栈顶元素{if(S.top-S.base>=S.stacksize){S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));if(!S.base){return ERROR;}S.top = S.base+S.stacksize;S.stacksize+= STACKINCREMENT;}*S.top++ = e;return OK;}Status Pop(SqStack &S,SElemType &e) // 若栈不空,则删除S的栈顶元素,用e返回//其值,并返// 回OK;否则返回ERROR{if(S.top==S.base){return ERROR;}e=* --S.top;return OK;}Status StackEmpty(SqStack S){ // 若栈S为空栈,则返回TRUE,否则返回FALSEif(S.base==S.top){return TRUE;}elsereturn FALSE;}// 队列操作Status InitQueue(LinkQueue &Q){Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front){return ERROR;}Q.front->next=NULL;return OK;}Status EnQueue( LinkQueue &Q,QElemType child) {QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p){return ERROR;}p->num=child;p->next=NULL;Q.rear->next=p;Q.rear=p;return OK;}Status DeQueue(LinkQueue &Q, QElemType &child) {QueuePtr p;if(Q.front==Q.rear)return ERROR;p=Q.front->next;child=p->num;Q.front->next=p->next;if(Q.rear==p){Q.rear=Q.front;}free(p);return OK;}Status QueueEmpty(LinkQueue Q){if(Q.front==Q.rear){return TRUE;}elsereturn FALSE;}Status DestroyQueue(LinkQueue &Q){while(Q.front){Q.rear=Q.front->next;free(Q.front);Q.front=Q.rear;}return OK;}BiTree createTree(BiTree &T) //建立空二叉树{T = (BiTNode *)malloc(sizeof(BiTNode));T= NULL;return T;}BiTree insert(BiTree &T,int ch) //元素插入{if(T==NULL){T = (BiTNode *)malloc(sizeof(BiTNode));T->lchild=NULL;T->rchild=NULL;T->data=ch;}else if (ch>T->data)T->rchild = insert(T->rchild,ch);elseT->lchild = insert(T->lchild,ch);return T;} //insertStatus find(BiTree T,int ch) //查找的关键字{int z;if(T==NULL){z=0;return z;}else if(ch>T->data)find(T->rchild,ch);else if(ch<T->data)find(T->lchild,ch);else{z=1;return z;}}Status PrintElement( int e ) // 输出元素e的值{printf("%d ", e );return OK;}Status PreOrderTraverse( BiTree T, Status(*Visit)(int)) //前序遍历{if(T){if(Visit(T->data))if(PreOrderTraverse(T->lchild,Visit))if(PreOrderTraverse( T->rchild, Visit))return OK;return ERROR;}else{return OK;}} // PreOrderTraverseStatus InOrderTraverse( BiTree T, Status(*Visit)(int) ) //递归中序遍历{if(T){if(InOrderTraverse(T->lchild,Visit))if(Visit(T->data))if(InOrderTraverse( T->rchild, Visit))return OK;return ERROR;}else{return OK;}}Status PostOrderTraverse( BiTree T, Status(*Visit)(int) ) 后序遍历{if(T){ if(PostOrderTraverse(T->lchild,Visit))if(PostOrderTraverse( T->rchild, Visit))if(Visit(T->data))return OK;return ERROR;}else{return OK;}}Status InOrderTraverse2(BiTree T,Status(*Visit)(int)) //非递归中序遍历{SqStack s;BiTree p;InitStack(s);p=T;while(p||!StackEmpty(s)){if(p){Push(s,p);p=p->lchild;}else{Pop(s,p);if(!Visit(p->data))return ERROR;p=p->rchild;}}return OK;}//层次遍历Status LevelOrderTraverse(BiTree T, Status (*Visit)(int)){LinkQueue Q; // 保存当前节点的左右孩子的队列BiTree p;InitQueue(Q); // 初始化队列if (T == NULL) return ERROR; //树为空则返回p = T; // 临时保存树根T到指针p中Visit(p->data); // 访问根节点if (p->lchild) EnQueue(Q, p->lchild); // 若存在左孩子,左孩子进队列if (p->rchild) EnQueue(Q, p->rchild); // 若存在右孩子,右孩子进队列while (!QueueEmpty(Q)) { // 若队列不空,则层序遍历DeQueue(Q, p); // 出队列Visit(p->data); // 访问当前节点if (p->lchild) EnQueue(Q, p->lchild); // 若存在左孩子,左孩子进队列if (p->rchild) EnQueue(Q, p->rchild); // 若存在右孩子,右孩子进队列}DestroyQueue(Q); // 释放队列空间return OK;}//计算最大深度Status TreeDeepth(BiTree T){int hl,hr,max;if(T){hl=TreeDeepth(T->lchild);hr=TreeDeepth(T->rchild);max=hl>hr?hl:hr;return max+1;}elsereturn 0;}//计算叶子总数Status countLeaf(BiTree T){if(T==NULL){return 0;}if(T->lchild==NULL&&T->rchild==NULL)return 1;return countLeaf(T->lchild)+countLeaf(T->rchild);}Status ChangeChild(BiTree &T) //交换左右结点{QElemType temp;if(T==NULL)return ERROR;ChangeChild(T->lchild);ChangeChild(T->rchild);temp=NULL;temp=T->lchild;T->lchild=T->rchild;T->rchild=temp;return OK;}int main() //主函数{BiTree s;int i,n,ch;int find1,find2;int inserts;scanf("%d",&n);createTree(s);for(i=0;i<n;i++){scanf("%d",&ch);insert(s,ch);}scanf("%d",&find1);scanf("%d",&find2);scanf("%d",&inserts);PreOrderTraverse( s,PrintElement );printf("\n");InOrderTraverse( s,PrintElement );printf("\n");PostOrderTraverse( s,PrintElement );printf("\n");printf("%d\n",find( s,find1));printf("%d\n",find( s,find2));insert(s,inserts);PreOrderTraverse( s,PrintElement );printf("\n");InOrderTraverse( s,PrintElement );printf("\n");PostOrderTraverse( s,PrintElement );printf("\n");InOrderTraverse2(s,PrintElement);printf("\n");LevelOrderTraverse(s, PrintElement);printf("\n");ChangeChild(s);PreOrderTraverse( s,PrintElement );printf("\n");InOrderTraverse( s,PrintElement );printf("\n");PostOrderTraverse( s,PrintElement );printf("\n");ChangeChild(s);PreOrderTraverse( s,PrintElement );printf("\n");InOrderTraverse( s,PrintElement );printf("\n");PostOrderTraverse( s,PrintElement );printf("\n");printf("%d\n",TreeDeepth(s));printf("%d\n",countLeaf(s));return OK;//补充代码}//main。

二叉树的建立与基本操作

二叉树的建立与基本操作

二叉树的建立与基本操作二叉树是一种特殊的树形结构,它由节点(node)组成,每个节点最多有两个子节点。

二叉树的基本操作包括建立二叉树、遍历二叉树、查找二叉树节点、插入和删除节点等。

本文将详细介绍二叉树的建立和基本操作,并给出相应的代码示例。

一、建立二叉树建立二叉树有多种方法,包括使用数组、链表和前序、中序、后序遍历等。

下面以使用链表的方式来建立二叉树为例。

1.定义二叉树节点类首先,定义一个二叉树节点的类,包含节点值、左子节点和右子节点三个属性。

```pythonclass Node:def __init__(self, value):self.value = valueself.left = Noneself.right = None```2.建立二叉树使用递归的方法来建立二叉树,先构造根节点,然后递归地构造左子树和右子树。

```pythondef build_binary_tree(lst):if not lst: # 如果 lst 为空,则返回 Nonereturn Nonemid = len(lst) // 2 # 取 lst 的中间元素作为根节点的值root = Node(lst[mid])root.left = build_binary_tree(lst[:mid]) # 递归构造左子树root.right = build_binary_tree(lst[mid+1:]) # 递归构造右子树return root```下面是建立二叉树的示例代码:```pythonlst = [1, 2, 3, 4, 5, 6, 7]root = build_binary_tree(lst)```二、遍历二叉树遍历二叉树是指按照其中一规则访问二叉树的所有节点,常见的遍历方式有前序遍历、中序遍历和后序遍历。

1.前序遍历前序遍历是指先访问根节点,然后访问左子节点,最后访问右子节点。

```pythondef pre_order_traversal(root):if root:print(root.value) # 先访问根节点pre_order_traversal(root.left) # 递归访问左子树pre_order_traversal(root.right) # 递归访问右子树```2.中序遍历中序遍历是指先访问左子节点,然后访问根节点,最后访问右子节点。

二叉树遍历典型例题

二叉树遍历典型例题

二叉树遍历典型例题正文:二叉树的遍历是指按照某种顺序访问二叉树中的所有节点。

常见的二叉树遍历方式有三种:前序遍历、中序遍历和后序遍历。

下面将以一个典型的例题来介绍这三种遍历方式的应用。

假设有一个二叉树如下所示:```1/2 3/4 5 6```首先介绍前序遍历。

前序遍历的顺序是先访问根节点,然后分别遍历左子树和右子树。

对于上面的二叉树,前序遍历的结果是1, 2, 4, 3, 5, 6。

接下来是中序遍历。

中序遍历的顺序是先遍历左子树,然后访问根节点,最后遍历右子树。

对于上面的二叉树,中序遍历的结果是2, 4, 1, 5, 3, 6。

最后是后序遍历。

后序遍历的顺序是先遍历左子树,然后遍历右子树,最后访问根节点。

对于上面的二叉树,后序遍历的结果是4, 2, 5, 6, 3, 1。

以上就是三种常见的二叉树遍历方式。

在实际应用中,二叉树的遍历经常用于查找、删除、插入等操作。

例如,在前序遍历中,可以用来复制一棵二叉树;在中序遍历中,可以用来对树进行排序;在后序遍历中,可以用来释放二叉树的内存等。

除了以上介绍的三种遍历方式,还存在一种更特殊的遍历方式,即层序遍历。

层序遍历是逐层访问二叉树节点的方式,从上到下、从左到右。

对于上面的二叉树,层序遍历的结果是1, 2, 3, 4, 5, 6。

在实际应用中,根据具体的问题要求,选择合适的遍历方式能够更加高效地解决问题。

因此,对于二叉树的遍历问题,我们需要熟练掌握各种遍历方式的特点和应用场景,以便于在实际问题中灵活运用。

二叉树基本操作经典实例

二叉树基本操作经典实例

二叉树基本操作经典实例二叉树是一种常见的数据结构,它由节点和指向左右子节点的指针组成。

二叉树的基本操作包括插入节点、删除节点、查找节点和遍历节点等。

在实际应用中,我们经常需要对二叉树进行基本操作,下面将介绍一些经典的例子。

一、插入节点插入节点是指向二叉树中添加一个新的节点。

在二叉树中插入节点的基本操作可以使用递归或者迭代的方法来实现。

下面是一个使用递归方法的示例代码:```public class TreeNodeint val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }public TreeNode insertNode(TreeNode root, int val)if (root == null)return new TreeNode(val);}if (val < root.val)root.left = insertNode(root.left, val);} else if (val > root.val)root.right = insertNode(root.right, val);}return root;```在上述代码中,通过递归的方式判断要插入的值和当前节点的大小关系,并将值插入到左子树或者右子树中,最后返回根节点。

二、删除节点删除节点是从二叉树中移除一个节点。

删除节点的基本操作可以分为三种情况:删除叶子节点、删除只有一个子节点的节点和删除有两个子节点的节点。

(1)删除叶子节点:如果要删除的节点是叶子节点,直接将该节点的父节点的指针指向空即可。

(2)删除只有一个子节点的节点:如果要删除的节点只有一个子节点,将该节点的子节点连接到该节点的父节点即可。

(3)删除有两个子节点的节点:如果要删除的节点有两个子节点,可以使用该节点右子树中的最小节点或者左子树中的最大节点来替代。

下面是一个使用递归方法的示例代码:```public TreeNode deleteNode(TreeNode root, int key) if (root == null)return root;}if (key < root.val)root.left = deleteNode(root.left, key);} else if (key > root.val)root.right = deleteNode(root.right, key);} elseif (root.left == null)return root.right;} else if (root.right == null)return root.left;}TreeNode minNode = findMin(root.right);root.val = minNode.val;root.right = deleteNode(root.right, minNode.val); }return root;private TreeNode findMin(TreeNode node)while (node.left != null)node = node.left;}return node;```在上述代码中,通过递归的方式判断要删除的值和当前节点的大小关系,并根据不同情况进行处理。

二叉树及二叉树的基本操作(基础篇)

二叉树及二叉树的基本操作(基础篇)

⼆叉树及⼆叉树的基本操作(基础篇)⼀、相关概念树是n( n>=0)个有限个数据的元素集合,它的数据的存储结构形状像⼀颗倒过来的树。

根在上,叶在下:如图所⽰1.⼀个独⽴的节点也可看作⼀棵树,它既为根节点,⼜为叶⼦节点;2.⼀个节点也没有称作空树;3.这是⼀颗典型的树,根节点为A;4.⼀个节点只有唯⼀⽗节点。

节点:结点包含数据和指向其它节点的指针。

根节点:树第⼀个结点称为根节点。

结点的度:结点拥有的⼦节点个数。

叶节点:没有⼦节点的节点(度为0)。

⽗⼦节点:⼀个节点father指向另⼀个节点child,则child为孩⼦节点, father为⽗亲节点。

兄弟节点:具有相同⽗节点的节点互为兄弟节点。

节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。

⼦孙:以某节点为根的⼦树中任⼀节点都称为该节点的⼦孙。

树的⾼度:树中距离根节点最远节点的路径长度。

如图⽰:5.树的存储结构1 struct TreeNode2 {3 DataType data; //节点值4 TreeNode* _firistchild; //第⼀个孩⼦5 TreeMode* _nextchild; //第⼆个孩⼦6 ...7 };有时候根据需要还会加⼊⽗节点,结构如下:1 struct TreeNode2 {3 DataType data; //节点值4 TreeNode* _parent;5 TreeNode* _firistchild; //第⼀个孩⼦6 TreeMode* _nextchild; //第⼆个孩⼦7 ...8 };⼆、⼆叉树1.⼆叉树:⼆叉树是⼀棵特殊的树,⼆叉树每个节点最多有两个孩⼦结点,分别称为左孩⼦和右孩⼦。

如图:2.存储结构1 template <class T>2 struct TreeNode //定义⼆叉树结点3 {5 TreeNode<T>* _left; //指向左⼦树的指针6 TreeNode<T>* _right; //指向右⼦树的指针7 T _data; //节点数据8 TreeNode(const T& n)9 :_left(NULL)10 ,_right(NULL)11 ,_data(n)12 {}13 };有时候根据需要还会加⼊⽗节点,结构如下:1 template <class T>2 struct TreeNode //定义⼆叉树结点3 {4 TreeNode<T>* _parent; //指向⽗节点的指针5 TreeNode<T>* _left; //指向左⼦树的指针6 TreeNode<T>* _right; //指向右⼦树的指针7 T _data; //节点数据8 TreeNode(const T& n)9 :_left(NULL)10 ,_right(NULL)11 ,_data(n)12 {}13 };3.特殊的⼆叉树满⼆叉树:⾼度为N的满⼆叉树有2^N - 1个节点的⼆叉树。

c语言二叉树的基本操作

c语言二叉树的基本操作

c语言二叉树的基本操作一、概念二叉树是一种数据结构,它由节点组成,每个节点都有0个或2个子节点,左子节点的关键字小于或等于该节点的关键字,右子节点的关键字大于该节点的关键字。

二、基本操作1、创建二叉树(1)结构体定义typedef struct node{int data; // 数据struct node *left; // 左子节点struct node *right; // 右子节点}Node, *pNode;(2)创建节点return p;}// 创建根节点*pTree = create_node(arr[0]);// 寻找合适的位置插入节点while (p != NULL){q = p;if (arr[i] < p->data)p = p->left;elsep = p->right;}2、遍历二叉树遍历二叉树有三种方法,分别是前序遍历、中序遍历和后序遍历。

(1)前序遍历void pre_order(pNode pTree){if (pTree != NULL){printf("%d ", pTree->data);pre_order(pTree->left);pre_order(pTree->right);}}3、查找节点找到关键字为data的节点,返回指向该节点的指针。

pNode search_node(pNode pTree, int data){if (pTree == NULL)return NULL;4、计算深度计算二叉树的深度,即为根节点到叶子节点的最长路径所包含的节点个数。

return left_depth > right_depth ? left_depth + 1 : right_depth + 1; }5、计算叶子节点数return leaf_count(pTree->left) + leaf_count(pTree->right);}6、删除节点删除节点分为两种情况:(1)被删除节点为叶子节点直接将其父节点指向该节点的指针设置为NULL即可。

二叉树的现实中典型例子

二叉树的现实中典型例子

二叉树的现实中典型例子二叉树是一种常用的数据结构,它具有广泛的应用。

下面列举了十个二叉树在现实中的典型例子。

一、文件系统文件系统是计算机中常见的二叉树应用之一。

文件系统中的目录和文件可以组织成一棵树,每个目录称为一个节点,而文件则是叶子节点。

通过树的结构,我们可以方便地对文件和目录进行管理和查找。

二、组织架构企业或组织的组织架构通常可以用二叉树来表示。

每个部门可以看作是一个节点,而员工则是叶子节点。

通过组织架构树,我们可以清晰地了解到企业或组织内部的管理层级关系。

三、家谱家谱是一个家族的血缘关系的记录,一般可以用二叉树来表示。

每个人可以看作是一个节点,而父子关系则是节点之间的连接。

通过家谱树,我们可以追溯家族的历史和血缘关系。

四、编译器编译器是将高级语言转换为机器语言的程序。

在编译过程中,编译器通常会使用语法分析树来表示源代码的结构。

语法分析树是一种特殊的二叉树,它将源代码表示为一个树状结构,方便进行语法分析和编译优化。

五、数据库索引数据库中的索引是一种用于提高数据查询效率的数据结构。

常见的索引结构包括B树和B+树,它们都是二叉树的变种。

通过索引树,数据库可以快速地定位到需要查询的数据,提高数据库的检索性能。

六、表达式求值在数学计算中,表达式求值是一项重要的任务。

通过使用二叉树,我们可以方便地表示和计算表达式。

二叉树的叶子节点可以是操作数,而内部节点可以是运算符。

通过遍历二叉树,我们可以按照正确的顺序对表达式进行求值。

七、电路设计在电路设计中,二叉树也有广泛的应用。

例如,我们可以使用二叉树来表示逻辑电路的结构,每个门电路可以看作是一个节点,而连接线则是节点之间的连接。

通过电路设计树,我们可以方便地进行电路的布线和优化。

八、图像处理图像处理是一项常见的计算机技术,而二叉树在图像处理中也有重要的应用。

例如,我们可以使用二叉树来表示图像的像素信息,每个像素可以看作是一个节点,而像素之间的关系则是节点之间的连接。

二叉树的几个经典例题

二叉树的几个经典例题

⼆叉树的⼏个经典例题⼆叉树遍历1题⽬描述编⼀个程序,读⼊⽤户输⼊的⼀串先序遍历字符串,根据此字符串建⽴⼀个⼆叉树(以指针⽅式存储)。

例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表⽰的是空格,空格字符代表空树。

建⽴起此⼆叉树以后,再对⼆叉树进⾏中序遍历,输出遍历结果。

输⼊描述:输⼊包括1⾏字符串,长度不超过100。

输出描述:可能有多组测试数据,对于每组数据,输出将输⼊字符串建⽴⼆叉树后中序遍历的序列,每个字符后⾯都有⼀个空格。

每个输出结果占⼀⾏。

输⼊abc##de#g##f###输出c b e gd f a思路:递归建树。

每次都获取输⼊字符串的当前元素,根据题⽬要求(先序、中序、后序等+其他限制条件)建树。

再根据题⽬要求输出即可。

1 #include<bits/stdc++.h>2using namespace std;3struct node{4char data;5 node *lchild,*rchild;6 node(char c):data(c),lchild(NULL),rchild(NULL){}7 };8string s;9int loc;10 node* create(){11char c=s[loc++];//获取每⼀个字符串元素12if(c=='#') return NULL;13 node *t=new node(c);//创建新节点14 t->lchild=create();15 t->rchild=create();16return t;17 }18void inorder(node *t){//递归中序19if(t){20 inorder(t->lchild);21 cout<<t->data<<'';22 inorder(t->rchild);23 }24 }25int main(){26while(cin>>s){27 loc=0;28 node *t=create();//先序遍历建树29 inorder(t);//中序遍历并输出30 cout<<endl;31 }32return0;33 }⼆叉树遍历2题⽬描述⼆叉树的前序、中序、后序遍历的定义:前序遍历:对任⼀⼦树,先访问跟,然后遍历其左⼦树,最后遍历其右⼦树;中序遍历:对任⼀⼦树,先遍历其左⼦树,然后访问根,最后遍历其右⼦树;后序遍历:对任⼀⼦树,先遍历其左⼦树,然后遍历其右⼦树,最后访问根。

c语言数据结构二叉树的基本操作 -回复

c语言数据结构二叉树的基本操作 -回复

c语言数据结构二叉树的基本操作-回复C语言数据结构:二叉树的基本操作概述:二叉树是一种常用的数据结构,在计算机科学中广泛应用于各种算法和问题的解决方案中。

它的特点是每个节点至多有两个子节点,即左子节点和右子节点,且子节点的顺序不能颠倒。

本文将介绍常见的二叉树基本操作,包括创建二叉树、插入节点、删除节点、查找节点、遍历等。

1. 创建二叉树:创建一个二叉树的方法是从根节点开始,逐个插入子节点。

首先定义一个二叉树的结构体,包含一个值和指向左右子节点的指针。

然后使用malloc 函数分配内存空间,并将值赋给根节点的指针。

接着创建左子节点和右子节点,将子节点的指针分别赋给根节点的左右指针。

这样就完成了一个简单的二叉树的创建。

2. 插入节点:插入节点是在现有的二叉树上新增一个节点。

首先找到插入节点的位置,可以从根节点开始逐级比较。

如果插入节点的值小于当前节点,则向左子树查找,否则向右子树查找,直到找到合适的位置。

然后创建一个新节点,并将新节点的指针赋给找到位置的节点的左或右指针。

3. 删除节点:删除节点是将现有的二叉树中的一个节点删除。

首先找到要删除的节点位置,可以通过比较节点的值进行查找,直到找到要删除的节点。

然后根据删除节点的情况分三种情况考虑:若删除节点为叶子节点,直接删除即可;若删除节点只有一个子节点,将子节点的指针赋给删除节点的父节点,然后删除删除节点;若删除节点有两个子节点,需要找到删除节点的左子树中的最大节点或右子树中的最小节点,将其值赋给删除节点,然后删除此最大或最小节点。

4. 查找节点:查找节点是在现有的二叉树中寻找一个特定的节点。

与插入和删除类似,从根节点开始比较节点的值,若要查找的节点值小于当前节点,则继续向左子树查找,否则向右子树查找,直到找到要查找的节点。

若找到了节点,返回此节点的指针;若未找到,返回空指针。

5. 遍历:遍历二叉树是按照一定的顺序访问树中的所有节点。

常见的遍历方式有三种:前序遍历、中序遍历和后序遍历。

二叉树的基本操作完整版,包含二叉树的所有操作,凡是你想要的都在里面--数据结构版

二叉树的基本操作完整版,包含二叉树的所有操作,凡是你想要的都在里面--数据结构版

#include "stdio.h"#include "stdlib.h"#include "string.h"#include "math.h"typedef char TElemType; //定义结点数据为字符型typedef int Status; //定义函数类型为int型#define ERROR 0#define OK 1typedef struct BiTNode{ //定义结构体TElemType data; //结点数值struct BiTNode *lchild; //左孩子指针struct BiTNode *rchild; //右孩子指针struct BiTNode *next; //下一结点指针}BiTNode, *BiTree;Status NumJudge(char ch[20]){//限制输入数据必须为大于零的整形char ch1[20];int num;while(1){scanf("%s",ch);num=atoi(ch); //将字符串转换为整型itoa(num,ch1,10); //将整型转换为字符串型if(strcmp(ch,ch1)==0&&num>0)break;else{printf("请输入一个大于零的整数: ");}}return num;}//NumJudgeStatus InitBiTree(BiTree &T){//构造空二叉树Tif(!(T=(BiTree)malloc(sizeof(BiTNode))))exit(ERROR); //若申请空间失败则退出T->next=NULL;printf("\n\t空二叉树构建成功!\n\n");return OK;}//InitBiTreeStatus DestroyTree(BiTree &T,BiTree t){//销毁二叉树if(T){free(T);T=NULL;printf("\t二叉树销毁成功!\n");}if(t){DestroyTree(T,t->lchild);DestroyTree(T,t->rchild);free(t);}return OK;}//DestroyTreeStatus ClearBiTree(BiTree &T,int sum,int &i){//清空二叉树if(T){ClearBiTree(T->lchild,sum,i);ClearBiTree(T->rchild,sum,i);free(T);i++;}if(i==sum){printf("\t二叉树清空成功!\n");T=NULL;}return OK;}//ClearBiTreeStatus CreateBiTree(BiTree &T,int i,int j,TElemType ch){//按先序次序输入二叉树中结点的值(一个字符),空格字符表示该结点为空//构造二叉链表示的二叉树TTElemType ch1;int k;char str[20];if(i==0){printf("\n 按先序顺序建立二叉树:请按提示输入相应的数据(一个字符),若提示结点数值为空,\n 请输入空格\n\n");printf("%5s请输入树根: "," ");}if(i!=0&&i>=j){printf("%5s请输入%c的左孩子: "," ",ch);}if(j!=0&&j>i){printf("%5s请输入%c的右孩子: "," ",ch);}while(1){ //限制输入数据必须为字符型,否则重新输入fflush(stdin);for(k=0;k<20;k++){str[k]=getchar();if(str[k]=='\n')break;}if(k==0)printf("%5s请输入一个字符后再按Enter键: "," ");if(k==1)break;if(k>1)printf("%5s您只能输入一个字符: "," ");}ch1=str[0]; //获取输入的准确字符型数据if(ch1==' '){T=NULL;return ERROR;} //输入空格则为根结点为空if(ch1!=' '){if(!(T=(BiTree)malloc(sizeof(BiTNode)))) exit(ERROR);T->data=ch1; //生成根结点ch=T->data;i++;CreateBiTree(T->lchild,i,j,ch); //构造左子树j=i;j++;CreateBiTree(T->rchild,i,j,ch); //构造右子树}i=0;j=0;return OK;}//CreateBitreeStatus TreeDepth(BiTree T,int l,int &h){//若二叉树存在,返回其深度if(T){l=l+1;if(l>h)h=l;TreeDepth(T->lchild,l,h);TreeDepth(T->rchild,l,h);}return h;}//TreeDepthStatus GetRootElem(BiTree T){//获取根结点值printf("该二叉树的根结点值为: %c\n\n",T->data);return OK;}//GetRootElemStatus SaveElem(BiTree T,BiTree *Q,int i){//根据完全二叉树中,若本节点位置序号为i,则其左孩子结点为2i,右孩子为2i+1的方法//保存二叉树的有效结点至指针数组Q特定的位置if(T){Q[i]=T;SaveElem(T->lchild,Q,2*i);SaveElem(T->rchild,Q,2*i+1);}return OK;}//SaveElemStatus Lev_Traverse(BiTree T,int h){//按层次从上到下,每层从左到右的顺序显示树状二叉树if(T==NULL){printf("\n\t\t二叉树目前为空树\n\n");return ERROR;}BiTree *Q;if(!(Q=(BiTree *)malloc(int(pow(2,h)+1) * sizeof(BiTNode))))exit(ERROR);int i,j,n=1,k=h;for(i=1;i<=int(pow(2,h)+1);i++){Q[i]=NULL;}SaveElem(T,Q,n); //将目前有效结点按照满二叉树的序号存储printf(" 提示:规定下图中的有效结点的位置序号从1开始按从上到下,从左到右的顺序依次递增\n");for(i=1;i<=(pow(2,h)+1);i++){ //树形显示二叉树if(int(pow(2,h))%i==0){printf("\n");printf("\t\t");for(j=0;j<pow(2,k-1)-1;j++){printf(" ");}k--;}if(Q[i])printf("%c",Q[i]->data);if(!Q[i])printf(" ");for(j=0;j<pow(2,k+1)-1;j++){printf(" ");}}printf("\n\n");i=0;j=0;return OK;}//Lev_TraverseStatus FirstPrint(BiTree T,int i){//按先序次序(递归)访问二叉树if(i==0)printf("\n先序(递归)遍历结果如下:\n");if(T){i++;printf("%-5c",T->data); //访问TFirstPrint(T->lchild,i); //递归遍历左子树FirstPrint(T->rchild,i); //递归遍历右子树}i=0;return OK;}//FirstPrintBiTreeStatus MiddlePrint(BiTree T,int i){//按中序次序(递归)访问二叉树if(i==0)printf("\n中序(递归)遍历结果如下:\n");if(T){i++;MiddlePrint(T->lchild,i); //递归遍历左子树printf("%-5c",T->data); //访问TMiddlePrint(T->rchild,i); //递归遍历右子树}i=0;return OK;}//MiddlePrintStatus LastPrint(BiTree T,int i){//按后序次序(递归)访问二叉树if(i==0)printf("\n后序(递归)遍历结果如下:\n");if(T){i++;LastPrint(T->lchild,i); //递归遍历左子树LastPrint(T->rchild,i); //递归遍历右子树printf("%-5c",T->data); //访问T}i=0;return OK;}//LastPrintStatus PreOrderTraverse(BiTree T){//按先序(非递归)遍历二叉树TBiTree p,S,q;int flag=0;if(!(S=(BiTree)malloc(sizeof(BiTNode))))exit(ERROR);S->next=NULL; //建立空栈Sp=T;printf("\n先序(非递归)遍历结果如下:\n");while(1){while(1){ //遍历存储并访问左子树直到根结点左孩子不存在printf("%-5c",p->data);q=S->next;S->next=p;p->next=q; //当前结点进栈if(p->lchild)p=p->lchild;else{break;}}while(1){ //栈顶指针出栈,如果当前栈顶指针的右孩子存在则跳出循环p=S->next;S->next=p->next;if(!S->next&&!p->rchild){flag=1;break;} //如果栈空并且当前结点右孩子不存在则遍历结束if(p->rchild){p=p->rchild;break;}}if(flag==1)break;}printf("\n\n");return OK;}//PreOrderTraverseStatus InOrderTraverse(BiTree T){// 中序遍历(非递归)二叉树TBiTree p,S,q;if(!(S=(BiTree)malloc(sizeof(BiTNode))))exit(ERROR);S->next=NULL; //建立空栈Sp=T;printf("\n中序(非递归)遍历结果如下:\n");while(p||S->next){if(p){q=S->next;S->next=p;p->next=q;p=p->lchild;} //左孩子进栈else{p=S->next;S->next=p->next;if(p)printf("%-5c",p->data); //输出栈中元素else{return ERROR;}p=p->rchild;}}printf("\n\n");return OK;}//InOrderTraverseStatus PostOrderTraverse(BiTree T){//后序遍历(非递归)二叉树TBiTree p,S,q;if(!(S=(BiTree)malloc(sizeof(BiTNode))))exit(ERROR);S->next=NULL; //建立空栈Sp=T;printf("\n后序(非递归)遍历结果如下:\n");while(1){while(1){ //遍历左子树,若当前结点左右孩子都不存在则跳出q=S->next;S->next=p;p->next=q; //当前结点进栈if(p->lchild)p=p->lchild;else{if(p->rchild)p=p->rchild;else{break;}}}while(S->next){p=S->next;S->next=p->next; //栈顶指针出栈并访问printf("%-5c",p->data);if(!S->next)break; //若栈空则跳出if(p==S->next->rchild)p=S->next; //若当前结点为栈顶指针的右孩子,则继续出栈else{if(S->next->rchild){ //栈顶指针右孩存在,指针移至栈顶指针的右孩子后跳出循环p=S->next->rchild;break;}}}if(!S->next)break; //若栈空则跳出循环}printf("\n\n");return OK;}//PostOrderTraverseStatus GetElemSum(BiTree T){//计算二叉树中总结点的个数BiTree p,*q;int l=0,h=0;if(!(q=(BiTree *)malloc(int(pow(2,TreeDepth(T,l,h))+1) * sizeof(BiTNode))))exit(ERROR);int head=1,tail=2;q[1]=T;while(head<tail){p=q[head++];if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}return head-1;}//GetElemSumStatus LevelOrderPrint(BiTree T){//二叉树T存在,层序遍历二叉树//将二叉树中的结点按从上到下,从左到右的顺序存至指针数组q,然后按次序输出BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int head=1,tail=2;q[1]=T;printf("\n层序(非递归)遍历结果如下:\n");while(head<tail){p=q[head++];printf("%-5c",p->data);if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}printf("\n\n");return OK;}//LevelOrderPrintStatus GetElemNum(BiTree T,TElemType e){//查找元素e在二叉树T中的个数及位置int j,i=0,num=0,*a;BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);if(!(a=(int *)malloc(GetElemSum(T) * sizeof(int))))exit(ERROR);int head=1,tail=2;q[1]=T;while(head<tail){p=q[head++];if(p->data==e){num++;a[i]=head-1;i++;}if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}printf("\n元素%c在二叉树中的个数为: %d\n",e,num);printf("元素%c在二叉树中的位置序号为:",e);for(j=0;j<i;j++){printf("%-4d",a[j]);}printf("\n");return num;}//GetElemNumStatus GetLeafNum(BiTree T){//计算二叉树T中叶子个数BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int num=0,head=1,tail=2;q[1]=T;while(head<tail){p=q[head++];if(!p->lchild&&!p->rchild)num++;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}return num;}//GetLeafNumStatus LBrother(BiTree T,int sum){//求第num个结点的左兄弟BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int i,num,head=1,tail=2;char str[20];q[1]=T;printf("请输入要查找的位置序号: ");num=NumJudge(str);if(num>sum){printf("您输入的位置序号大于有效结点个数\n");return ERROR;};while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(num==1)printf("位置%d的%c没有左兄弟\n",num,q[num]->data);else{for(i=1;i<num;i++){if(q[i]->lchild==q[num]||q[i]->rchild==q[num])break;}if(q[i]->lchild==q[num])printf("位置%d的%c没有左兄弟\n",num,q[num]->data);if(q[i]->rchild==q[num])printf("位置%d的%c的左兄弟为: %c\n",num,q[num]->data,q[i]->lchild->data);}return OK;}//LBrotherStatus RBrother(BiTree T,int sum){//求第num个结点的右兄弟BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int i,num,head=1,tail=2;char str[20];q[1]=T;printf("请输入要查找的位置序号: ");num=NumJudge(str);if(num>sum){printf("您输入的位置序号大于有效结点个数\n");return ERROR;};while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(num==1)printf("位置%d的%c没有右兄弟\n",num,q[num]->data);else{for(i=1;i<num;i++){if(q[i]->lchild==q[num]||q[i]->rchild==q[num])break;}if(!q[i]->rchild||q[i]->rchild==q[num])printf("位置%d的%c没有右兄弟\n",num,q[num]->data);if(q[i]->rchild&&q[i]->lchild==q[num])printf("位置%d的%c的右兄弟为: %c\n",num,q[num]->data,q[i]->rchild->data);}return OK;}//RBrotherStatus Lchild(BiTree T,int sum){//求第num个结点的左孩子BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int num,head=1,tail=2;char str[20];q[1]=T;printf("请输入要查找的位置序号: ");num=NumJudge(str);if(num>sum){printf("您输入的位置序号大于有效结点个数\n");return ERROR;}while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(q[num]->lchild)printf("位置%d的%c的左孩子为: %c\n",num,q[num]->data,q[num]->lchild->data);else{printf("位置%d的%c的左孩子不存在\n",num,q[num]->data);}return OK;}//LchildStatus Rchild(BiTree T,int sum){//求第num个结点的右孩子BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int num,head=1,tail=2;char str[20];q[1]=T;printf("请输入要查找的位置序号: ");num=NumJudge(str);if(num>sum){printf("您输入的位置序号大于有效结点个数\n");return ERROR;}while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(q[num]->rchild)printf("位置%d的%c的右孩子为: %c\n",num,q[num]->data,q[num]->rchild->data);else{printf("位置%d的%c的右孩子不存在\n",num,q[num]->data);}return OK;}//RchildStatus Partents(BiTree T,int sum){//求第num个结点的双亲BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int i,num,head=1,tail=2;char str[20];q[1]=T;printf("请输入要查找的位置序号: ");num=NumJudge(str);if(num>sum){printf("您输入的位置序号大于有效结点个数\n");return ERROR;}while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(num==1)printf("位置%d的%c没有双亲\n",num,q[num]->data);else{for(i=1;i<num;i++){if(q[i]->lchild==q[num]||q[i]->rchild==q[num])break;}printf("位置%d的%c的双亲为: %c\n",num,q[num]->data,q[i]->data);}return OK;}//PartentsStatus TreeDelete(BiTree &T,int sum){//删除第num个结点BiTree p,p1,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int i,num,head=1,tail=2,a=0,b=0;char str[20];q[1]=T;printf("请输入要删除结点的位置序号: ");num=NumJudge(str);if(num>sum){printf("\n您输入的位置序号大于有效结点个数\n\n");return ERROR;}if(num==1){printf("\t对不起,您不能删除根结点,若想删除根结点,请选择销毁树\n\n");return ERROR;};while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}for(i=1;i<num;i++){if(q[i]->lchild==q[num]||q[i]->rchild==q[num])break;}printf("\n您删除了如下子树:\n\n");Lev_Traverse(q[num],TreeDepth(q[num],a,b));if(q[i]->lchild==q[num])q[i]->lchild=NULL;if(q[i]->rchild==q[num])q[i]->rchild=NULL;p1=NULL;DestroyTree(p1,q[num]);printf("\n删除结点成功\n");return OK;}//TreeDeleteStatus TreeInsert(BiTree &T,int sum){//在第num个生成子树BiTree p,p1,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int num,head=1,tail=2,a=0,b=0;char ch=' ',str[20];q[1]=T;printf("请输入要插入结点的位置序号: ");num=NumJudge(str);if(num>sum){printf("\n您输入的位置序号大于有效结点个数\n\n");return ERROR;}while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}if(q[num]->lchild&&q[num]->rchild){printf("您输入的位置序号已有左子树和右子树,无法再此位置插入\n\n");return ERROR;}if(q[num]->lchild&&!q[num]->rchild){printf("位置%d的%c处只能生成右子树,确定插入/退出(y/n): ",num,q[num]->data);while(1){scanf("%s",str);if(strcmp(str,"y")==0||strcmp(str,"n")==0)break;else{printf("选择错误,请重新输入: ");}}if(strcmp(str,"y")==0){printf("请输入插入子树的信息: \n");CreateBiTree(p1,a,b,ch);if(p1){q[num]->rchild=p1;}}if(strcmp(str,"n")==0)return ERROR;}if(!q[num]->lchild&&q[num]->rchild){printf("位置%d的%c处只能生成左子树,确定插入/退出(y/n): ",num,q[num]->data);while(1){scanf("%s",str);if(strcmp(str,"y")==0||strcmp(str,"n")==0)break;else{printf("选择错误,请重新输入: ");}}if(strcmp(str,"y")==0){printf("请输入插入子树的信息: \n");CreateBiTree(p1,a,b,ch);if(p1){q[num]->lchild=p1;}}if(strcmp(str,"n")==0)return ERROR;}if(!q[num]->lchild&&!q[num]->rchild){printf("请输入插入子树的信息: \n");CreateBiTree(p1,a,b,ch);printf("\t\t你想把新建的树作为位置%d的%c处的: \n",num,q[num]->data);printf("\t\t [1]左子树[2]右子树\n");printf("\n\t\t请输入你的选择: ");while(1){scanf("%s",str);if(strcmp(str,"1")==0||strcmp(str,"2")==0)break;else{printf("选择错误,请重新输入: ");}}if(strcmp(str,"1")==0){if(p1){q[num]->lchild=p1;}}if(strcmp(str,"2")==0){if(p1){q[num]->rchild=p1;}}}printf("插入子树成功\n");return OK;}//TreeInsertStatus Modify(BiTree T,int sum,int &n){//修改二叉树第num个结点的值BiTree p,*q;if(!(q=(BiTree *)malloc(GetElemSum(T) * sizeof(BiTNode))))exit(ERROR);int k,num,head=1,tail=2;char str[20];q[1]=T;n=0;printf("请输入要修改结点的位置序号: ");num=NumJudge(str);if(num>sum){printf("\n您输入的位置序号大于有效结点个数\n\n");return ERROR;} while(head<tail){p=q[head++];if(num==tail-2)break;if(p->lchild)q[tail++]=p->lchild;if(p->rchild)q[tail++]=p->rchild;}printf("%5s请输入新的结点值: "," ");while(1){fflush(stdin);for(k=0;k<20;k++){str[k]=getchar();if(str[k]=='\n')break;}if(k==0)printf("%5s请输入一个字符后再按Enter键: "," ");if(k==1)break;if(k>1)printf("%5s您只能输入一个字符: "," ");}q[num]->data=str[0];printf("\n 修改成功\n");n=1;return OK;}//Modifyint MainMenu(){ //主菜单函数system("cls");int choose;char str[20];printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t 计本102 卢荣盼1018014052");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t [1]建立空树\n");printf("\n\t\t\t [2]构造二叉树\n");printf("\n\t\t\t [3]显示树状二叉树\n");printf("\n\t\t\t [4]遍历二叉树->>进入子菜单\n");printf("\n\t\t\t [5]查看二叉树信息->>进入子菜单\n");printf("\n\t\t\t [6]对二叉树进行操作->>进入子菜单\n");printf("\n\t\t\t [0]退出程序");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t请输入你的选择: ");while(1){scanf("%s",str);if(strcmp(str,"0")==0||strcmp(str,"1")==0||strcmp(str,"2")==0||strcmp(str,"3")==0 ||strcmp(str,"4")==0||strcmp(str,"5")==0||strcmp(str,"6")==0){choose=atoi(str);break;}else{printf("\t\t\t选择错误请重新输入: ");}}if(choose==0){printf("\n\n\t…~~~…~~~谢谢使用本程序~~~…~~~…\n\n");} return choose;}//MainMenu()int Menu(){ //主菜单函数system("cls");int choose;char str[20];printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t 请选择对应的选项按对应的方式遍历二叉树");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t\t[1]按先序(递归)遍历二叉树\n");printf("\n\t\t\t\t[2]按中序(递归)遍历二叉树\n");printf("\n\t\t\t\t[3]按后序(递归)遍历二叉树\n");printf("\n\t\t\t\t[4]按先序(非递归)遍历二叉树\n");printf("\n\t\t\t\t[5]按中序(非递归)遍历二叉树\n");printf("\n\t\t\t\t[6]按后序(非递归)遍历二叉树\n");printf("\n\t\t\t\t[7]按层次(非递归)遍历二叉树\n");printf("\n\t\t\t\t[0]返回主菜单");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=*\n");printf("\t\t\t请输入你的选择: ");while(1){scanf("%s",str);if(strcmp(str,"0")==0||strcmp(str,"1")==0||strcmp(str,"2")==0||strcmp(str,"3")==0 ||strcmp(str,"4")==0||strcmp(str,"5")==0||strcmp(str,"6")==0||strcmp(str,"7")==0) {choose=atoi(str);break;}else{printf("\t\t\t选择错误请重新输入: ");}}return choose;}//Menu()int Menu1(){ //查看二叉树信息菜单system("cls");int choose;char str[20],str1[20];printf("\n\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=* =*=*=*=*");printf("\n\t 请选择对应的选项查看当前二叉树的信息");printf("\n\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=* =*=*=*=*");printf("\n\t [1]返回根结点值[2]二叉树的深度\n");printf("\n\t [3]二叉树的总结点个数[4]二叉树中度为2的结点个数\n");printf("\n\t [5]二叉树中度为1的结点个数[6]二叉树中叶子结点个数\n");printf("\n\t [7]某一值的结点个数及位置[8]二叉树中某结点的左孩子\n");printf("\n\t [9]二叉树中某结点的右孩子[10]二叉树中某结点的左兄弟\n");printf("\n\t [11]二叉树中某结点的右兄弟[12]二叉树中某结点的双亲\n");printf("\n\t [0]返回主菜单\n");printf("\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=*=*=**=**=*=*=**=*= *=*=*=*=*\n");printf("\t\t请输入你的选择: ");while(1){scanf("%s",str);choose=atoi(str);itoa(choose,str1,10);if(choose>0&&choose<=12&&strcmp(str,str1)==0||strcmp(str,"0")==0)break;else{printf("\t\t选择错误请重新输入: ");}}return choose;}//Menu1()int Menu2(){ //主菜单函数system("cls");int choose;char str[20];printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=*");;printf("\n\t\t\t 请选择对应的选项对二叉树进行操作");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t\t[1]删除某一结点\n");printf("\n\t\t\t\t[2]对某一结点生成子树\n");printf("\n\t\t\t\t[3]修改某一结点值\n");printf("\n\t\t\t\t[4]清空二叉树\n");printf("\n\t\t\t\t[5]销毁二叉树\n");printf("\n\t\t\t\t[0]返回主菜单");printf("\n\t\t\t*=*=*=*=*=*=*=**=*=*=**=*=*=**=*=*=*");printf("\n\t\t\t请输入你的选择: ");while(1){scanf("%s",str);if(strcmp(str,"0")==0||strcmp(str,"1")==0||strcmp(str,"2")==0||strcmp(str,"3")==0 ||strcmp(str,"4")==0||strcmp(str,"5")==0){choose=atoi(str);break;}else{printf("\t\t\t选择错误请重新输入: ");}}return choose;}//Menu2()void main(){system("color e0");BiTree T=NULL;int num,l,h,choose,flag=0,i=0,j=0,n;TElemType ch;while((choose=MainMenu())!=0){switch(choose){case 1:if(flag==2){printf("您已清空了之前的二叉树,目前为空树,无须再建立空树!\n\n");} else{if(flag==0){InitBiTree(T);flag=1;}else{printf("您之前已经建过空树,若想重建,请先销毁当前的树!\n\n");}} system("pause");break;case 2:if(!T)printf("您还没有建树,请先建树!\n\n");else{if(T->next)printf("二叉树已存在,若想重建,请先清空当前的二叉树!\n\n");else{system("cls");CreateBiTree(T->next,i,j,ch);printf("\n\n二叉树创建完成!\n\n");}}system("pause");break;case 3:if(!T)printf("您还没有建树,请先建树!\n\n");else{l=0;h=0;if(T->next){printf("\n 当前二叉树的树状图如下:\n\n");}Lev_Traverse(T->next,TreeDepth(T->next,l,h));}system("pause");break;case 4:if(!T){printf("您还没有建树,请先建树!\n\n");system("pause");}else{if(!T->next){printf("二叉树目前为空树,请创建非空树后再遍历!\n\n");system("pause");}else{while((choose=Menu())!=0){l=0;h=0;printf("\n 当前二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));switch(choose){case 1:FirstPrint(T->next,i);printf("\n\n");system("pause");break;case 2:MiddlePrint(T->next,i);printf("\n\n");system("pause");break;case 3:LastPrint(T->next,i);printf("\n\n");system("pause");break;case 4:PreOrderTraverse(T->next);system("pause");break;case 5:InOrderTraverse(T->next);system("pause");break;case 6:PostOrderTraverse(T->next);system("pause");break;case 7:LevelOrderPrint(T->next);printf("\n\n");system("pause");break;default:exit(ERROR);}}}}break;case 5:if(!T){printf("您还没有建树,请先建树!\n\n");system("pause");}else{if(!T->next){printf("二叉树目前为空树,请创建非空树后再查看信息!\n\n");system("pause");}else{while((choose=Menu1())!=0){l=0;h=0;printf("\n 当前二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));switch(choose){case 1:GetRootElem(T->next);system("pause");break;case 2:printf("当前二叉树的深度为: %d\n\n",TreeDepth(T->next,l,h));system("pause");break;case 3:printf("\n二叉树中有效结点的个数为: %d\n\n",GetElemSum(T->next));system("pause");break;case 4:printf("\n二叉树中度为2的结点个数为: %d\n\n",GetLeafNum(T->next)-1);system("pause");break;case 5:printf("\n二叉树中度为1的结点个数为: %d\n\n",GetElemSum(T->next)-2*GetLeafNum(T->next)+1);system("pause");break;case 6:printf("\n二叉树中叶子结点个数为: %d\n\n",GetLeafNum(T->next));system("pause");break;case 7:printf("请输入要统计的元素: ");fflush(stdin);scanf("%c",&ch);GetElemNum(T->next,ch);system("pause");break;case 8:Lchild(T->next,GetElemSum(T->next));system("pause");break;case 9:Rchild(T->next,GetElemSum(T->next));system("pause");break;case 10:LBrother(T->next,GetElemSum(T->next));system("pause");break;case 11:RBrother(T->next,GetElemSum(T->next));system("pause");break;case 12:Partents(T->next,GetElemSum(T->next));system("pause");break;default:exit(ERROR);}}}}break;case 6:if(!T){printf("您还没有建树,请先建树!\n\n");system("pause");}else{if(!T->next){printf("二叉树目前为空树,请创建非空树后再对树进行操作!\n\n");system("pause");}else{while((choose=Menu2())!=0){if(choose!=4&&choose!=5){system("cls");l=0;h=0;printf("\n 当前二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));printf("\n二叉树中有效结点的个数为: %d\n\n",GetElemSum(T->next));printf("当前二叉树的深度为: %d\n\n",h);}switch(choose){case 1:num=GetElemSum(T->next);TreeDelete(T->next,GetElemSum(T->next));if(num!=GetElemSum(T->next)){l=0;h=0;printf("\n 删除后二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));printf("\n二叉树中有效结点的个数为: %d\n\n",GetElemSum(T->next));printf("当前二叉树的深度为: %d\n\n",h);}system("pause");break;case 2:num=GetElemSum(T->next);TreeInsert(T->next,GetElemSum(T->next));if(num!=GetElemSum(T->next)){l=0;h=0;printf("\n 插入后二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));printf("\n二叉树中有效结点的个数为: %d\n\n",GetElemSum(T->next));printf("当前二叉树的深度为: %d\n\n",h);}system("pause");break;case 3:Modify(T->next,GetElemSum(T->next),n);if(n==1){l=0;h=0;printf("\n 修改后二叉树的树状图如下:\n\n");Lev_Traverse(T->next,TreeDepth(T->next,l,h));printf("\n二叉树中有效结点的个数为: %d\n\n",GetElemSum(T->next));printf("当前二叉树的深度为: %d\n\n",h);}system("pause");break;case 4:h=0;ClearBiTree(T->next,GetElemSum(T->next),h);flag=2;break;case 5:DestroyTree(T,T->next);flag=0;break;default:exit(ERROR);}if(choose==4){printf("\n\t您已清空了当前的二叉树,程序将退回到主菜单,请重新建树后再回本菜单操作!\n\n");system("pause");break;}if(choose==5){printf("\n\t您已销毁了当前的二叉树,程序将退回到主菜单,请重新建树后再回本菜单操作!\n\n");system("pause");break;}}}}break;default:exit(ERROR);}}}。

实验3 二叉树的操作及应用

实验3 二叉树的操作及应用

实验3 二叉树的操作及应用PB13000818 焦孟娇实验目的:1. 熟练掌握递归程序设计的方法。

2. 掌握二叉树的特性和基本算法。

问题描述:二叉树是一种基本且常用的数据结构。

二叉树的很多基本算法都可以用递归的形式来表述。

本实验要求实现二叉树的如下操作:创建、销毁、复制、打印显示、先中后序遍历、查找元素、层序遍历、求二叉树的深度、宽度、结点数和叶子个数等。

实验内容:一、队列的抽象数据类型定义为:Queue operation{数据对象:数据关系:基本操作:InitQueue(&S)操作结果:构造一个空队列SQueueLength(S)初始条件:队列S已存在操作结果:返回S的元素个数,即队列的长度QueueEmpty(S)初始条件:队列S已存在操作结果:若S为空队列,则返回TRUE,否则FALSEEnQueue(&S, e)初始条件:队列S已存在操作结果:插入元素e为队列新元素DeQueue(&S, &e)初始条件:队列S已存在且非空操作结果:删除S的队头元素,并用e返回其值GetHead(S, &e)初始条件:队列S已存在且非空操作结果:用e返回S的队头元素ClearQueue(&S)初始条件:队列S已存在操作结果:将S清为空队列DeleteQueue(&S)初始条件:队列S已存在操作结果:队列S被销毁Print(S)初始条件:队列S已存在操作结果:输出队列S} Queue operationBiTree operation{InitBiTree( &T )// 操作结果:构造空二叉树T。

DestroyBiTree( &T )// 初始条件:二叉树T已存在。

// 操作结果:销毁二叉树T。

CreateBiTree( &T, definition )// 初始条件:definition给出二叉树T的定义。

// 操作结果:按definiton构造二叉树T。

c语言数据结构二叉树的基本操作

c语言数据结构二叉树的基本操作

c语言数据结构二叉树的基本操作在 C 语言中,二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

以下是二叉树的一些基本操作的示例:1. 创建二叉树:```c#include <stdio.h>#include <stdlib.h>// 定义二叉树节点结构体struct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;};// 创建二叉树struct TreeNode* createTree(int data) {struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));if (newNode == NULL) {printf("内存分配失败\n");exit(1);}newNode->data = data;newNode->left = NULL;newNode->right = NULL;return newNode;}```在上述示例中,我们定义了一个二叉树节点结构体 `TreeNode`,它包含一个整数类型的数据成员 `data`,以及两个指向左右子节点的指针成员 `left` 和 `right`。

然后,我们使用 `malloc` 函数分配一个 `TreeNode` 结构体的内存空间,并将其赋值给 `newNode` 变量。

如果内存分配失败,我们输出错误信息并终止程序。

最后,我们初始化 `newNode` 的数据成员,并将左右子节点设置为 `NULL`,表示它们还没有被赋值。

2. 插入节点:```c// 在二叉树中插入节点void insertNode(struct TreeNode* root, int data) {if (root == NULL) {root = createTree(data);return;}if (data < root->data) {insertNode(root->left, data);} else if (data > root->data) {insertNode(root->right, data);}}```在上述示例中,我们定义了一个函数 `insertNode`,用于在二叉树中插入节点。

二叉树的创建与应用实例

二叉树的创建与应用实例

二叉树的创建与应用实例一、引言二叉树是一种非常常见的数据结构,它在很多领域都有着广泛的应用,如文件系统、计算机科学、数据挖掘等。

了解和掌握二叉树的结构和应用,对于深入理解数据结构和算法是非常有帮助的。

本篇文档将详细介绍二叉树的创建以及应用实例。

二、二叉树的基本概念二叉树是一种递归定义的数据结构,它由一个根节点和两个子节点(分别称为左子树和右子树)组成。

二叉树的每个节点最多有两个子节点,这使得二叉树具有高度优化和紧凑性的特点。

三、二叉树的创建创建二叉树通常有两种方式:手动创建和通过算法创建。

1.手动创建:手动创建二叉树需要按照二叉树的定义规则,逐个创建节点并连接它们。

这种方式的优点是直观易懂,缺点是手动创建大量的节点会比较繁琐。

2.算法创建:算法创建二叉树通常使用递归的方式,通过特定的算法步骤逐个构建节点。

这种方式可以自动化地创建大量的二叉树,而且效率较高。

四、二叉树的应用实例1.文件系统:文件系统中的目录结构可以看作是一种特殊的二叉树,其中根节点是整个文件系统的入口,左子节点表示子目录,右子节点表示文件。

通过二叉树可以方便地管理和查找文件。

2.计算机科学:在计算机科学中,二叉树常用于表示程序的执行路径,如决策树、堆栈等。

此外,二叉树也常用于数据压缩和哈希算法等。

3.数据挖掘:在数据挖掘中,二叉树常用于分类和聚类算法,如决策树、k-means等。

通过构建二叉树,可以将数据集划分为不同的类别,从而更好地理解和分析数据。

五、应用实例代码展示下面是一个简单的Python代码示例,展示了如何手动创建一个简单的二叉搜索树(BinarySearchTree,BST):```pythonclassNode:def__init__(self,key):self.left=Noneself.right=Noneself.val=keydefinsert(root,key):ifrootisNone:returnNode(key)else:ifroot.val<key:root.right=insert(root.right,key)else:root.left=insert(root.left,key)returnrootdefinorder(root):ifroot:inorder(root.left)print(root.val),inorder(root.right)r=Node(50)r=insert(r,30)r=insert(r,20)r=insert(r,40)r=insert(r,70)r=insert(r,60)r=insert(r,80)print("Inordertraversalofthegiventree")inorder(r)#Output:20304050607080```六、总结本篇文档详细介绍了二叉树的创建以及应用实例,包括二叉树的基本概念、创建方式以及在文件系统、计算机科学、数据挖掘等领域的应用。

python二叉树用法

python二叉树用法

python二叉树用法Python是一种高级编程语言,广泛应用于各个领域。

在数据结构和算法中,二叉树是一种常见的数据结构,具有广泛的应用。

本文将介绍Python中二叉树的用法,包括创建二叉树、插入节点、删除节点、遍历二叉树等操作。

一、创建二叉树在Python中,可以使用类和节点的方式创建二叉树。

下面是一个示例代码:```pythonclass Node:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef insert(root, value):if root is None:root = Node(value)else:if value < root.value:if root.left is None:root.left = Node(value)else:insert(root.left, value)else:if root.right is None:root.right = Node(value)else:insert(root.right, value)root = Node(5)insert(root, 3)insert(root, 7)insert(root, 2)insert(root, 4)insert(root, 6)insert(root, 8)```二、插入节点在二叉树中插入节点需要遵循一定的规则。

具体操作如下:1. 如果二叉树为空,则直接将节点作为根节点。

2. 如果插入的值小于当前节点的值,则将节点插入到当前节点的左子树中。

3. 如果插入的值大于当前节点的值,则将节点插入到当前节点的右子树中。

4. 如果当前节点的左/右子树不为空,则将当前节点的左/右子树作为新的根节点,递归执行步骤2和步骤3,直到找到插入位置。

三、删除节点在二叉树中删除节点也需要遵循一定的规则。

二叉排序树的基本操作

二叉排序树的基本操作

二叉排序树的基本操作
二叉排序树
二叉排序树(Binary Sort Tree),又称二叉查找树、二叉搜索树,是指一棵空
树或者具有下列性质的二叉树:
二叉排序树的基本操作
二叉排序树包括了以下几种基本操作:
在二叉排序树中插入新的数据是就是将新的数据和二叉排序树中的节点进行比较,如果新的数据比节点的数据小,就将新的数据放在节点的左边;如果新的数据比节点的数据大,就将新的数据放在节点的右边,这样对整棵树依次重复比较,直到找到一个空节点位置将新数据插入进去。

删除操作是比较复杂的,需要做三步:第一步是查找到要删除的节点;第二步是找到这个节点的“前驱”节点;第三步是将“前驱”节点替换到要删除的节点上。

具体步骤:
查找操作是最常用的操作。

查找操作的思路与插入操作有点类似,也是用新数据和二叉排序树中的节点进行比较。

如果新的数据比节点的数据小,就转到左子树;如果新的数据比节点的数据大,就转到右子树,这样就能够找到新数据在二叉排序树中的位置。

总结
二叉排序树是一种应用比较广泛的数据结构,它具有查找、插入、删除等常见数据操作方式。

其中,插入操作是将新数据依次与树中节点进行比较,如果新数据比节点的数据小,就放在节点的左边;而查找操作则是和插入操作相似,只不过是找所需要的数据而已。

最后,删除操作则需要先找到要删除的节点,然后找到“前驱”节点并将其替换到要删除的节点上,最终再将“前驱”节点删除。

二叉树基本操作

二叉树基本操作

二叉树基本操作二叉树基本操作一、实验目的1.熟悉二叉树结点的结构和对二叉树的基本操作。

2.掌握对二叉树每一种操作的具体实现。

3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。

4.在二叉树基本操作的基础上掌握对二叉树的一些其它操作的具体实现方法。

5.掌握构造哈夫曼树以及哈夫曼编码的方法。

二、实验内容(必做1)程序 1该程序的功能是实现二叉树结点的类型定义和对二叉树的基本操作。

该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。

/* 定义 DataType 为char类型 */typedef char DataType;/* 二叉树的结点类型 */typedef struct BitNode{DataType data;struct BitNode *lchild,*rchild;}BitNode,*BitTree;/* 初始化二叉树,即把树根指针置空 */void BinTreeInit(BitTree *BT)/* 按先序次序建立一个二叉树*/void BinTreeCreat(BitTree *BT)/* 检查二叉树是否为空 */int BinTreeEmpty(BitTree *BT)/* 按任一种遍历次序(包括按先序、中序、后序、按层次)输出二叉树中的所有结点 */void BinTraverse(BitTree *BT)/* 求二叉树的深度 */int BinTreeDepth(BitTree BT)/* 求二叉树中所有结点数 */int BinTreeCount(BitTree BT)/* 清除二叉树,使之变为空树 */void BinTreeClear(BitTree *BT)程序2 二叉树采用二叉链表存储,设计按层次遍历二叉树的算法。

设计要求:在程序中构造两个子程序分别为void BinTreeCreat(BitTree *BT) /* 按前序次序建立一个二叉树*/ void layorder(BitTree T) /*按层次遍历二叉树 */程序 3哈夫曼树和哈夫曼编码:从终端输入若干个字符,统计字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各字符进行哈夫曼编码。

c语言实现二叉树各种基本运算的算法

c语言实现二叉树各种基本运算的算法

c语言实现二叉树各种基本运算的算法二叉树是一种常见的数据结构,可以应用于许多算法和问题中。

在C语言中,我们可以使用指针和结构体来实现二叉树的各种基本运算。

本文将详细介绍二叉树的创建、插入、删除、查找以及遍历等基本操作的算法。

1.创建二叉树创建二叉树可以通过递归的方式来实现。

首先定义一个表示二叉树节点的结构体,包含一个值和左右子节点指针。

然后,通过递归地创建左右子树来构建整个二叉树。

```ctypedef struct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;} TreeNode;//创建二叉树TreeNode* createBinaryTree() {int data;scanf("%d", &data);if (data == -1) { // -1表示空节点return NULL;}TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->data = data;node->left = createBinaryTree();node->right = createBinaryTree();return node;}```2.插入节点在二叉树中插入节点可以按照二叉搜索树的性质进行。

如果要插入的值小于当前节点的值,则将其插入到左子树中,否则插入到右子树中。

如果子树为空,则直接创建一个新节点作为子树。

```c//插入节点TreeNode* insertNode(TreeNode* root, int data) {if (root == NULL) {TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));newNode->data = data;newNode->left = NULL;newNode->right = NULL;return newNode;}if (data < root->data) {root->left = insertNode(root->left, data);} else {root->right = insertNode(root->right, data);}return root;}```3.删除节点删除二叉树中的节点可以分为三种情况:删除叶子节点、删除只有一个子节点的节点、删除有两个子节点的节点。

C语言中二叉树常见的基本操作和C代码语言图文总结

C语言中二叉树常见的基本操作和C代码语言图文总结

C语言中二叉树常见的基本操作和C代码语言图文总结1.1 前序遍历对于当前结点,先输出该结点,然后输出它的左孩子,最后输出它的右孩子。

以上图为例,递归的过程如下:1.输出 1,接着左孩子;2.输出 2,接着左孩子;3.输出 4,左孩子为空,再接着右孩子;4.输出 6,左孩子为空,再接着右孩子;5.输出 7,左右孩子都为空,此时 2 的左子树全部输出,2 的右子树为空,此时 1 的左子树全部输出,接着 1 的右子树;6.输出 3,接着左孩子;7.输出 5,左右孩子为空,此时 3 的左子树全部输出,3 的右子树为空,至此 1 的右子树全部输出,结束。

而非递归版本只是利用 stack 模拟上述过程而已,递归的过程也就是出入栈的过程。

/* 前序遍历递归版*/void PreOrderRec(Node * node){if (node == nullptr)return;cout << node->data << " "; // 先输出当前结点PreOrderRec(node->left); // 然后输出左孩子PreOrderRec(node->right); // 最后输出右孩子}/* 前序遍历非递归版*/void PreOrderNonRec(Node * node){if (node == nullptr)return;stack S;cout << node->data << " ";S.push(node);node = node->left;while (!S.empty() || node){while (node){cout << node->data << " "; // 先输出当前结点S.push(node);node = node->left; // 然后输出左孩子}// while 结束意味着左孩子已经全部输出node = S.top()->right; // 最后输出右孩子S.pop();}}1.2 中序遍历对于当前结点,先输出它的左孩子,然后输出该结点,最后输出它的右孩子。

二叉树的基本操作

二叉树的基本操作

二叉树的基本操作看东西容易,写东西确实就复杂多了呀,花了两天时间把二叉树的数据结构及一些相关基本算法的原理认真研究了下,并写出了相应的代码,包括二叉树的前序创建、前中后序遍历、层序遍历、删除、通过前序和中序序列构造二叉树等等#include <stdio.h>//定义数据元素类型typedef int Element;//定义二叉树节点typedef struct bitree{Element data;struct bitree *left, *right;} Bitree;//定义队列节点,层序遍历typedef struct queueNode{Bitree * data;struct queueNode *next;} QueueNode;typedef struct queue{QueueNode *front, *rear;} Queue;//创建队列void createQueue(Queue **Q){*Q = (Queue *) malloc(sizeof(Queue));if(!*Q)exit("Memory error...\n");(*Q)->front = (*Q)->rear = NULL;}//入队操作void EnQueue(Queue *Q, Bitree *data){QueueNode * qn = (QueueNode*) malloc(sizeof(QueueNode));if(!qn)exit("Memory error...\n");qn->data = data;qn->next = NULL;if(IsQueueEmpty(Q))Q->front = Q->rear = qn;else{Q->rear->next = qn;Q->rear = qn;}}//出队操作void DeQueue(Queue *Q, Bitree **T){if(!IsQueueEmpty(Q)){QueueNode *qn = Q->front;(*T) = qn->data;Q->front = qn->next;free(qn);qn = NULL;}}//判断队列是否为空int IsQueueEmpty(Queue *Q){if(!Q->front)return 1;return 0;}//二叉树的创建void createBitree(Bitree **T){Element data;scanf("%d", &data);if(data != 0){(*T) = (Bitree*)malloc(sizeof(Bitree)); if(!*T)exit("Memory error...\n");(*T)->data = data;(*T)->left = (*T)->right = NULL;createBitree(&(*T)->left);createBitree(&(*T)->right);}}//根据前序和中序遍历结果生成二叉树(总是假设给定的序列是有效的,这里不进行错误检测)//@param p 递归前序子序列的起始位置//@param m 递归中序子序列的起始位置//@param length 递归子序列的长度void creByPreMid(Bitree **T, int p, int m, int length, int *pre, int *mid) {int i=0;for(;(i<length)&&(pre[p]!=mid[m+i]);i++);(*T) = (Bitree *) malloc(sizeof(Bitree));if(!*T)exit("Memory error...\n");(*T)->data = pre[p];(*T)->left = (*T)->right = NULL;//若有左子树则创建左子树if(i>0){creByPreMid(&(*T)->left, p+1, m, i, pre, mid);}//若有右子树则创建右子树if(i<length-1){creByPreMid(&(*T)->right, p+1+i, m+i+1, length-i-1, pre, mid); }}//删除树void delBitree(Bitree **T){if(*T){delBitree(&(*T)->left);delBitree(&(*T)->right);free(*T);*T = NULL;}}//二叉树的前序遍历void preOrder(Bitree *T){if(T){printf("%d ", T->data);preOrder(T->left);preOrder(T->right);}}//二叉树的中序遍历void midOrder(Bitree *T){if(T){midOrder(T->left);printf("%d ", T->data);midOrder(T->right);}}//二叉树的后序遍历void afterOrder(Bitree *T){if(T){afterOrder(T->left);afterOrder(T->right);printf("%d ", T->data);}}//二叉树的层序遍历//思路:利用队列,如果树不为空,将根节点入队// 然后循环队头元素出队,并作一下处理:判断出队的节点是否有左孩子,有则将左孩子入队,判断出队的节点是否有右孩子,有则将又孩子入队。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

本程序由SOGOF完成该完整程序主要是递归函数的使用及模板的使用,完成了对二叉树基本的链表操作,主要有二叉树的建立,前序、中序、后序遍历,求树的高度,每层结点数(包含树的最大宽度),左右结点对换,二叉树的内存释放,求解树的叶子数。

#include<iostream>using namespace std;#define FLAG'#'typedef char Record;template<typename Entry>struct Binary_Node{Entry data;Binary_Node<Entry>*left;Binary_Node<Entry>*right;Binary_Node();Binary_Node(const Entry& x);};template<typename Entry>Binary_Node<Entry>::Binary_Node(){left=NULL;right=NULL;}template<typename Entry>Binary_Node<Entry>::Binary_Node(const Entry &x){data=x;left=NULL;right=NULL;}template<class T>class Binary_tree{public:bool empty()const;Binary_tree();Binary_tree(Binary_tree<T>&org);void create_tree(Binary_Node<T>*&tree);//建立二叉树void recursive_copy(Binary_Node<T>*&tree,Binary_Node<T>*&cur);void pre_traverse(Binary_Node<T> *tree);//前序void mid_traverse(Binary_Node<T> *tree);//中序void post_traverse(Binary_Node<T> *tree);//后序遍历void count_node(Binary_Node<T> *tree,int &count);//计算结点数void count_leaves(Binary_Node<T> *tree,int &count);//计算叶子数int tree_height(Binary_Node<T> *tree);//树的高度void Ltree_To_Rtree(Binary_Node<T>*tree);//左右树互换void count_width(Binary_Node<T> *tree,int *count_width,int count);//计算树的最大宽度int get_count()const;//得到树的结点数Binary_Node<T>*get_root()const;void destroy_tree(Binary_Node<T> *tree);//删除数Binary_tree<T>&operator=(Binary_tree&org);protected:T*pre_visit;T*mid_visit;Binary_Node<T>*root;int node_numb;};template<class T>Binary_tree<T>::Binary_tree(){root=NULL;node_numb=0;}template<class T>voidBinary_tree<T>::recursive_copy(Binary_Node<T>*&tree,Binary_Node<T>*&cur) {if(tree==NULL){return;}else{cur=new Binary_Node<T>(tree->data);node_numb++;recursive_copy(tree->left,cur->left);recursive_copy(tree->right,cur->right);}}template<class T>Binary_tree<T>::Binary_tree( Binary_tree<T>&org)recursive_copy(org.root,root);}template<class T>Binary_tree<T>& Binary_tree<T>::operator =(Binary_tree<T>&org) {recursive_copy(org.root,root);return *this;}template<class T>bool Binary_tree<T>::empty() const{return root==NULL;}template<class T>int Binary_tree<T>::get_count()const{return node_numb;}template<class T>void Binary_tree<T>::create_tree(Binary_Node<T>*&tree){T val;cout<<"请输入数据,若空以#输入: ";cin>>val;tree=new Binary_Node<T>(val);if(val==FLAG){tree=NULL;return;}else{node_numb++;if(root==NULL)root=tree;create_tree(tree->left);create_tree(tree->right);}template<class T>Binary_Node<T>* Binary_tree<T>::get_root() const{return root;}template<class T>void Binary_tree<T>::count_node(Binary_Node<T> *tree,int& count){if(tree){count++;count_node(tree->left,count);count_node(tree->right,count);}}template<class T>void Binary_tree<T>::count_leaves(Binary_Node<T> *tree,int& count){if(tree){ if((tree->left==NULL)&&(tree->right==NULL))count++;count_leaves(tree->left,count);count_leaves(tree->right,count);}}template<class T>void Binary_tree<T>::count_width(Binary_Node<T> *tree,int *count_mid,int count) {if(tree){if(tree!=root)count++;count_width(tree->left,count_mid,count);count_width(tree->right,count_mid,count);count_mid[count]++;}}template<class T>int Binary_tree<T>::tree_height(Binary_Node<T> *tree){int count_left=0, count_right=0;if(tree==NULL)return 0;else{count_left=tree_height(tree->left);count_right=tree_height(tree->right);return(count_left>count_right)?(count_left+1):(count_right+1);}}template<class T>void Binary_tree<T>::Ltree_To_Rtree(Binary_Node<T>*tree){if(tree){Ltree_To_Rtree(tree->left);Ltree_To_Rtree(tree->right);if(tree->left!=NULL||tree->right!=NULL){Binary_Node<T>*temp=tree->left;tree->left=tree->right;tree->right=temp;}}}template<class T>void Binary_tree<T>::destroy_tree(Binary_Node<T> *tree){if(tree){Binary_Node<T> *parent=tree;destroy_tree(tree->left);destroy_tree(tree->right);if(parent==root){delete root;root=NULL;parent=NULL;node_numb--;}else{delete parent;parent=NULL;node_numb--;}}}template<class T>void Binary_tree<T>::pre_traverse(Binary_Node<T> *tree) {if(root==NULL){cout<<"树为空,不能遍历"<<endl;return;}if(tree){cout<<" "<<tree->data;pre_traverse(tree->left);pre_traverse(tree->right);}}template<class T>void Binary_tree<T>::mid_traverse(Binary_Node<T> *tree) {if(root==NULL){cout<<"树为空,不能遍历"<<endl;return;}if(tree){mid_traverse(tree->left);cout<<" "<<tree->data;mid_traverse(tree->right);}}template<class T>void Binary_tree<T>::post_traverse(Binary_Node<T> *tree) {if(root==NULL){cout<<"树为空,不能遍历"<<endl;return;}if(tree){post_traverse(tree->left);post_traverse(tree->right);cout<<" "<<tree->data;}}void main(){int m=0,leaves=0,Tree_height;Binary_tree<Record>Tree;Binary_Node<Record>*pp;Tree.create_tree(pp);Binary_tree<Record>Tree1(Tree);cout<<"前序遍历结果为:";Tree.pre_traverse(Tree.get_root());cout<<endl<<"中序遍历结果为:";Tree.mid_traverse(Tree.get_root());cout<<endl<<"后序遍历结果为:";Tree.post_traverse(Tree.get_root());cout<<endl;Tree.count_node(Tree.get_root(),m);cout<<"结点个数为:"<<m<<endl;Tree.count_leaves(Tree.get_root(),leaves);cout<<"叶子个数为:"<<leaves<<endl;Tree_height=Tree.tree_height(Tree.get_root());cout<<"树高度为:"<<Tree_height<<endl;m=0;int *count_wid=new int[Tree_height];for(int i=0;i<Tree_height;i++)count_wid[i]=0;Tree.count_width(Tree.get_root(),count_wid,m);int Max=count_wid[0];m=0;for(int i=0;i<Tree_height;i++){cout<<"在第"<<i<<"层,共有结点"<<count_wid[i]<<"个"<<endl;if(Max<count_wid[i]){Max=count_wid[i];m=i;}}cout<<"在第"<<m<<"层结点最多,共有结点"<<Max<<"个"<<endl;Tree.Ltree_To_Rtree(Tree.get_root());Tree.destroy_tree(Tree.get_root());delete []count_wid;}树如下:(a)(b) (c)(d) (e) (f) (g)输入:输出:。

相关文档
最新文档