二叉树的建立遍历vc++
二叉树的建立与先序中序后序遍历 求叶子节点个数 求分支节点个数 求二叉树的高度
/*一下总结一些二叉树的常见操作:包括建立二叉树先/中/后序遍历二叉树求二叉树的叶子节点个数求二叉树的单分支节点个数计算二叉树双分支节点个数计算二叉树的高度计算二叉树的所有叶子节点数*/#include<stdio.h> //c语言的头文件#include<stdlib.h>//c语言的头文件stdlib.h千万别写错了#define Maxsize 100/*创建二叉树的节点*/typedef struct BTNode //结构体struct 是关键字不能省略结构体名字可以省略(为无名结构体)//成员类型可以是基本型或者构造形,最后的为结构体变量。
{char data;struct BTNode *lchild,*rchild;}*Bitree;/*使用先序建立二叉树*/Bitree Createtree() //树的建立{char ch;Bitree T;ch=getchar(); //输入一个二叉树数据if(ch==' ') //' '中间有一个空格的。
T=NULL;else{ T=(Bitree)malloc(sizeof(Bitree)); //生成二叉树(分配类型*)malloc(分配元素个数*sizeof(分配类型))T->data=ch;T->lchild=Createtree(); //递归创建左子树T->rchild=Createtree(); //地柜创建右子树}return T;//返回根节点}/*下面先序遍历二叉树*//*void preorder(Bitree T) //先序遍历{if(T){printf("%c-",T->data);preorder(T->lchild);preorder(T->rchild);}} *//*下面先序遍历二叉树非递归算法设计*/void preorder(Bitree T) //先序遍历非递归算法设计{Bitree st[Maxsize];//定义循环队列存放节点的指针Bitree p;int top=-1; //栈置空if(T){top++;st[top]=T; //根节点进栈while(top>-1) //栈不空时循环{p=st[top]; //栈顶指针出栈top--;printf("%c-",p->data );if(p->rchild !=NULL) //右孩子存在进栈{top++;st[top]=p->rchild ;}if(p->lchild !=NULL) //左孩子存在进栈{top++;st[top]=p->lchild ;}}printf("\n");}}/*下面中序遍历二叉树*//*void inorder(Bitree T) //中序遍历{if(T){inorder(T->lchild);printf("%c-",T->data);inorder(T->rchild);}}*//*下面中序遍历二叉树非递归算法设计*/void inorder(Bitree T) //中序遍历{Bitree st[Maxsize]; //定义循环队列,存放节点的指针Bitree p;int top=-1;if(T){p=T;while (top>-1||p!=NULL) //栈不空或者*不空是循环{while(p!=NULL) //扫描*p的所有左孩子并进栈{top++;st[top]=p;p=p->lchild ;}if(top>-1){p=st[top]; //出栈*p节点,它没有右孩子或右孩子已被访问。
二叉树的遍历及常用算法
⼆叉树的遍历及常⽤算法⼆叉树的遍历及常⽤算法遍历的定义:按照某种次序访问⼆叉树上的所有结点,且每个节点仅被访问⼀次;遍历的重要性:当我们需要对⼀颗⼆叉树进⾏,插⼊,删除,查找等操作时,通常都需要先遍历⼆叉树,所有说:遍历是⼆叉树的基本操作;遍历思路:⼆叉树的数据结构是递归定义(每个节点都可能包含相同结构的⼦节点),所以遍历也可以使⽤递归,即结点不为空则继续递归调⽤每个节点都有三个域,数据与,左孩⼦指针和右孩⼦之指针,每次遍历只需要读取数据,递归左⼦树,递归右⼦树,这三个操作三种遍历次序:根据访问三个域的不同顺序,可以有多种不同的遍历次序,⽽通常对于⼦树的访问都按照从左往右的顺序;设:L为遍历左⼦树,D为访问根结点,R为遍历右⼦树,且L必须位于R的前⾯可以得出以下三种不同的遍历次序:先序遍历操作次序为DLR,⾸先访问根结点,其次遍历根的左⼦树,最后遍历根右⼦树,对每棵⼦树同样按这三步(先根、后左、再右)进⾏中序遍历操作次序为LDR,⾸先遍历根的左⼦树,其次访问根结点,最后遍历根右⼦树,对每棵⼦树同样按这三步(先左、后根、再右)进⾏后序遍历操作次序为LRD,⾸先遍历根的左⼦树,其次遍历根的右⼦树,最后访问根结点,对每棵⼦树同样按这三步(先左、后右、最后根)进⾏层次遍历层次遍历即按照从上到下从左到右的顺序依次遍历所有节点,实现层次遍历通常需要借助⼀个队列,将接下来要遍历的结点依次加⼊队列中;遍历的应⽤“遍历”是⼆叉树各种操作的基础,可以在遍历过程中对结点进⾏各种操作,如:对于⼀棵已知⼆叉树求⼆叉树中结点的个数求⼆叉树中叶⼦结点的个数;求⼆叉树中度为1的结点个数求⼆叉树中度为2的结点个数5求⼆叉树中⾮终端结点个数交换结点左右孩⼦判定结点所在层次等等...C语⾔实现:#include <stdio.h>//⼆叉链表数据结构定义typedef struct TNode {char data;struct TNode *lchild;struct TNode *rchild;} *BinTree, BinNode;//初始化//传⼊⼀个指针令指针指向NULLvoid initiate(BinTree *tree) {*tree = NULL;}//创建树void create(BinTree *BT) {printf("输⼊当前结点值: (0则创建空节点)\n");char data;scanf(" %c", &data);//连续输⼊整形和字符时.字符变量会接受到换⾏,所以加空格if (data == 48) {*BT = NULL;return;} else {//创建根结点//注意开辟的空间⼤⼩是结构体的⼤⼩⽽不是结构体指针⼤⼩,写错了不会⽴马产⽣问题,但是后续在其中存储数据时极有可能出现内存访问异常(飙泪....) *BT = malloc(sizeof(struct TNode));//数据域赋值(*BT)->data = data;printf("输⼊节点 %c 的左孩⼦ \n", data);create(&((*BT)->lchild));//递归创建左⼦树printf("输⼊节点 %c 的右孩⼦ \n", data);create(&((*BT)->rchild));//递归创建右⼦树}}//求双亲结点(⽗结点)BinNode *Parent(BinTree tree, char x) {if (tree == NULL)return NULL;else if ((tree->lchild != NULL && tree->lchild->data == x) || (tree->rchild != NULL && tree->rchild->data == x))return tree;else{BinNode *node1 = Parent(tree->lchild, x);BinNode *node2 = Parent(tree->rchild, x);return node1 != NULL ? node1 : node2;}}//先序遍历void PreOrder(BinTree tree) {if (tree) {//输出数据printf("%c ", tree->data);//不为空则按顺序继续递归判断该节点的两个⼦节点PreOrder(tree->lchild);PreOrder(tree->rchild);}}//中序void InOrder(BinTree tree) {if (tree) {InOrder(tree->lchild);printf("%c ", tree->data);InOrder(tree->rchild);}}//后序void PostOrder(BinTree tree) {if (tree) {PostOrder(tree->lchild);PostOrder(tree->rchild);printf("%c ", tree->data);}}//销毁结点递归free所有节点void DestroyTree(BinTree *tree) {if (*tree != NULL) {printf("free %c \n", (*tree)->data);if ((*tree)->lchild) {DestroyTree(&((*tree)->lchild));}if ((*tree)->rchild) {DestroyTree(&((*tree)->rchild));}free(*tree);*tree = NULL;}}// 查找元素为X的结点使⽤的是层次遍历BinNode *FindNode(BinTree tree, char x) {if (tree == NULL) {return NULL;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];if (current->data == x) {return current;}front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}return NULL;}//层次遍历// 查找元素为X的结点使⽤的是层次遍历void LevelOrder(BinTree tree) {if (tree == NULL) {return;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];printf("%2c", current->data);front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}}//查找x的左孩⼦BinNode *Lchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->lchild;}return NULL;}//查找x的右孩⼦BinNode *Rchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->rchild;}return NULL;}//求叶⼦结点数量int leafCount(BinTree *tree) {if (*tree == NULL)return 0;//若左右⼦树都为空则该节点为叶⼦,且后续不⽤接续递归了else if (!(*tree)->lchild && !(*tree)->rchild)return 1;else//若当前结点存在⼦树,则递归左右⼦树, 结果相加return leafCount(&((*tree)->lchild)) + leafCount(&((*tree)->rchild));}//求⾮叶⼦结点数量int NotLeafCount(BinTree *tree) {if (*tree == NULL)return 0;//若该结点左右⼦树均为空,则是叶⼦,且不⽤继续递归else if (!(*tree)->lchild && !(*tree)->rchild)return 0;else//若当前结点存在左右⼦树,则是⾮叶⼦结点(数量+1),在递归获取左右⼦树中的⾮叶⼦结点,结果相加 return NotLeafCount(&((*tree)->lchild)) + NotLeafCount(&((*tree)->rchild)) + 1;}//求树的⾼度(深度)int DepthCount(BinTree *tree) {if (*tree == NULL)return 0;else{//当前节点不为空则深度+1 在加上⼦树的⾼度,int lc = DepthCount(&((*tree)->lchild)) + 1;int rc = DepthCount(&((*tree)->rchild)) + 1;return lc > rc?lc:rc;// 取两⼦树深度的最⼤值 }}//删除左⼦树void RemoveLeft(BinNode *node){if (!node)return;if (node->lchild)DestroyTree(&(node->lchild));node->lchild = NULL;}//删除右⼦树void RemoveRight(BinNode *node){if (!node)return;if (node->rchild)DestroyTree(&(node->rchild));node->rchild = NULL;}int main() {BinTree tree;create(&tree);BinNode *node = Parent(tree, 'G');printf("G的⽗结点为%c\n",node->data);BinNode *node2 = Lchild(tree, 'D');printf("D的左孩⼦结点为%c\n",node2->data);BinNode *node3 = Rchild(tree, 'D');printf("D的右孩⼦结点为%c\n",node3->data);printf("先序遍历为:");PreOrder(tree);printf("\n");printf("中序遍历为:");InOrder(tree);printf("\n");printf("后序遍历为:");PostOrder(tree);printf("\n");printf("层次遍历为:");LevelOrder(tree);printf("\n");int a = leafCount(&tree);printf("叶⼦结点数为%d\n",a);int b = NotLeafCount(&tree);printf("⾮叶⼦结点数为%d\n",b);int c = DepthCount(&tree);printf("深度为%d\n",c);//查找F节点BinNode *node4 = FindNode(tree,'C');RemoveLeft(node4);printf("删除C的左孩⼦后遍历:");LevelOrder(tree);printf("\n");RemoveRight(node4);printf("删除C的右孩⼦后遍历:");LevelOrder(tree);printf("\n");//销毁树printf("销毁树 \n");DestroyTree(&tree);printf("销毁后后遍历:");LevelOrder(tree);printf("\n");printf("Hello, World!\n");return 0;}测试:测试数据为下列⼆叉树:运⾏程序复制粘贴下列内容:ABDGHECKFIJ特别感谢:iammomo。
二叉树遍历(前序、中序、后序、层次、广度优先、深度优先遍历)
⼆叉树遍历(前序、中序、后序、层次、⼴度优先、深度优先遍历)⽬录转载:⼆叉树概念⼆叉树是⼀种⾮常重要的数据结构,⾮常多其他数据结构都是基于⼆叉树的基础演变⽽来的。
对于⼆叉树,有深度遍历和⼴度遍历,深度遍历有前序、中序以及后序三种遍历⽅法,⼴度遍历即我们寻常所说的层次遍历。
由于树的定义本⾝就是递归定义,因此採⽤递归的⽅法去实现树的三种遍历不仅easy理解并且代码⾮常简洁,⽽对于⼴度遍历来说,须要其他数据结构的⽀撑。
⽐⽅堆了。
所以。
对于⼀段代码来说,可读性有时候要⽐代码本⾝的效率要重要的多。
四种基本的遍历思想前序遍历:根结点 ---> 左⼦树 ---> 右⼦树中序遍历:左⼦树---> 根结点 ---> 右⼦树后序遍历:左⼦树 ---> 右⼦树 ---> 根结点层次遍历:仅仅需按层次遍历就可以⽐如。
求以下⼆叉树的各种遍历前序遍历:1 2 4 5 7 8 3 6中序遍历:4 2 7 5 8 1 3 6后序遍历:4 7 8 5 2 6 3 1层次遍历:1 2 3 4 5 6 7 8⼀、前序遍历1)依据上⽂提到的遍历思路:根结点 ---> 左⼦树 ---> 右⼦树,⾮常easy写出递归版本号:public void preOrderTraverse1(TreeNode root) {if (root != null) {System.out.print(root.val+" ");preOrderTraverse1(root.left);preOrderTraverse1(root.right);}}2)如今讨论⾮递归的版本号:依据前序遍历的顺序,优先訪问根结点。
然后在訪问左⼦树和右⼦树。
所以。
对于随意结点node。
第⼀部分即直接訪问之,之后在推断左⼦树是否为空,不为空时即反复上⾯的步骤,直到其为空。
若为空。
则须要訪问右⼦树。
注意。
在訪问过左孩⼦之后。
c语言实现二叉树的四种遍历和求深度与叶子个数
c语言实现二叉树的四种遍历和求深度与叶子个数二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。
在C语言中,我们可以使用指针来实现二叉树的操作。
本文将介绍四种常见的二叉树遍历方式,以及如何求解二叉树的深度和叶子节点个数。
首先,我们需要定义一个二叉树节点的结构体,包含一个数据域和两个指针域,分别指向左子节点和右子节点。
代码如下:```cstruct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;};```接下来,我们可以实现二叉树的四种遍历方式:前序遍历、中序遍历、后序遍历和层序遍历。
前序遍历是指先访问根节点,然后递归地遍历左子树和右子树。
代码如下:```cvoid preorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}printf("%d ", root->data);preorderTraversal(root->left);preorderTraversal(root->right);}```中序遍历是指先递归地遍历左子树,然后访问根节点,最后递归地遍历右子树。
代码如下:```cvoid inorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}inorderTraversal(root->left);printf("%d ", root->data);inorderTraversal(root->right);}```后序遍历是指先递归地遍历左子树和右子树,最后访问根节点。
代码如下:```cvoid postorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}postorderTraversal(root->left);postorderTraversal(root->right);printf("%d ", root->data);}```层序遍历是按照树的层次逐层遍历节点。
数据结构-二叉树的存储结构和遍历
return(p); }
建立二叉树
以字符串的形式“根左子树右子树”定义 一棵二叉树
1)空树 2)只含一个根 结点的二叉树 A 3)
B C
A
以空白字符“ ”表示
以字符串“A ”表示
D
以下列字符串表示 AB C D
建立二叉树 A B C C
T
A ^ B ^ C^ ^ D^
D
建立二叉树
Status CreateBiTree(BiTree &T) {
1 if (!T) return;
2 Inorder(T->lchild, visit); // 遍历左子树 3 visit(T->data); } // 访问结点 4 Inorder(T->rchild, visit); // 遍历右子树
后序(根)遍历
若二叉树为空树,则空操
根
左 子树
右 子树
作;否则, (1)后序遍历左子树; (2)后序遍历右子树; (3)访问根结点。
统计二叉树中结点的个数
遍历访问了每个结点一次且仅一次
设置一个全局变量count=0
将visit改为:count++
统计二叉树中结点的个数
void PreOrder (BiTree T){ if (! T ) return; count++; Preorder( T->lchild); Preorder( T->rchild); } void Preorder (BiTree T,void( *visit)(TElemType& e)) { // 先序遍历二叉树 1 if (!T) return; 2 visit(T->data); // 访问结点 3 Preorder(T->lchild, visit); // 遍历左子树 4 Preorder(T->rchild, visit);// 遍历右子树 }
实验8 线索二叉树的创建和遍历
实验八线索二叉树的创建和遍历1.实验目的(1)掌握二叉树的线索链表存储结构。
(2)能够实现二叉树的线索链表的创建、遍历等基本操作。
2.实验内容编程实现二叉树的线索链表存储表示的基本操作,包括线索二叉树的创建与遍历。
3.实验要求(1)根据实验内容编写程序,上机调试并获得运行结果(2)撰写实验报告4.准备工作本次实验将会构造此二叉树,并会对此二叉树进行遍历5.关键步骤与算法(1)构造线索二叉树算法步骤;若某节点的左孩子节点指针域(lchild)为空,就可以利用它来指出该节点在某种遍历序列中的直接前驱的存储地址;若某节点的右孩子指针域(rchild)为空,就可以利用它来指出该节点在某种遍历序列中的直接后继的存储地址。
那些非空的指针域仍存放指向该节点左、右孩子节点的指针域。
这样,就得到了一棵线索二叉树。
算法如下;1.//按先序遍历序列输入树中各节点的值,构造线索二叉树2.BiThrTree* CreateBiThrTree()3.{4. BiThrTree *s;5. DataType ch;6. scanf("%c",&ch);7.8.if(ch == '#')9. exit(0);10.if(ch == '@')11. s = NULL;12.else if (ch=='\n')13. getchar();14.15.else16. {17. s = (BiThrTree *)malloc(sizeof(BiThrTree));18.if(!s)19. exit(ERROR);20. s->data = ch;21. s->lflag = 0;22. s->rflag = 0;23. s->lchild = CreateBiThrTree();24. s->rchild = CreateBiThrTree();25. }26.return s;27.}(2) 将二叉树中序线索化现将树递归到左子树然后再判断这个树的左右子树是否为空,如果为空则把它们的标志设为1,代表线索,首先设一个current代表前驱结点,然后判断它是否为空,如果为空则进行下一次递归,如果不为空,则判断左标志和右标志如果左标志为线索,则让前驱节点的右孩子指向当前节点,如果右标志为1,则让当前节点的左孩子指向前驱结点算法如下;1.void InThreading(BiThrTree *t)2.{3.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数4. {5. InThreading(t->lchild);//递归调用左子树进行线索化6.if(t->lchild == NULL)7. t->lflag = 1;8.if(t->rchild == NULL)9. t->rflag = 1;10.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上111.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL12. {13.if(current->rflag == 1)14. current->rchild = t;//前驱结点的右孩子指针指向当前节点t15.if(t->lflag == 1)16. t->lchild = current;//现结点t的左孩子指针指向前驱结点17. }18. current = t;//让前驱结点为t为下一次执行函数做准备19. InThreading(t->rchild);//递归调用右子树进行线索化20. }21.}6.源代码1.#include<malloc.h>2.#include<stdio.h>3.#include<stdlib.h>4.#include<io.h>5.#define ERROR -16.7.typedef char DataType;8.typedef struct BiThrNode//二叉树的二叉链表的存储结构9.{10. DataType data;11.struct BiThrNode *lchild,*rchild;12.int lflag,rflag;//左右标志,值为0表示指针,值为1表示线索13.}BiThrTree;14.BiThrTree *current = NULL;15.//检查if的==16.//按先序遍历序列输入树中各节点的值,构造线索二叉树17.BiThrTree* CreateBiThrTree()18.{19. BiThrTree *s;20. DataType ch;21. scanf("%c",&ch);22.23.if(ch == '#')24. exit(0);25.if(ch == '@')26. s = NULL;27.else if (ch=='\n')28. getchar();29.30.else31. {32. s = (BiThrTree *)malloc(sizeof(BiThrTree));33.if(!s)34. exit(ERROR);35. s->data = ch;36. s->lflag = 0;37. s->rflag = 0;38. s->lchild = CreateBiThrTree();39. s->rchild = CreateBiThrTree();40. }41.return s;42.}43.//将二叉树前序线索化(递归)44.void PreThreading(BiThrTree *t)45.{46.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数47. {48.if(t->lchild == NULL)49. t->lflag = 1;50.if(t->rchild == NULL)51. t->rflag = 1;52.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上153.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL54. {55.if(current->rflag == 1)56. current->rchild = t;//前驱结点的右孩子指针指向当前节点t57.if(t->lflag == 1)58. t->lchild = current;//现结点t的左孩子指针指向前驱结点59. }60. current = t;//让前驱结点为t为下一次执行函数做准备61.if(t->lflag == 0)62. PreThreading(t->lchild);//递归调用右子树进行线索化63.if(t->rflag == 0)64. PreThreading(t->rchild);65. }66.}67.//遍历前序线索二叉树68.void PreVisitThrtree(BiThrTree *t)69.{70.while(t != NULL)//大循环71. {72.while(t->lflag == 0)73. {74. printf("%c\t",t->data);75. t = t->lchild;76. }77. printf("%c\t",t->data);78. t = t->rchild;79. }80.}81.82.//检查if的==83.//将二叉树中序线索化(递归)84.void InThreading(BiThrTree *t)85.{86.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数87. {88. InThreading(t->lchild);//递归调用左子树进行线索化89.if(t->lchild == NULL)90. t->lflag = 1;91.if(t->rchild == NULL)92. t->rflag = 1;93.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上194.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL95. {96.if(current->rflag == 1)97. current->rchild = t;//前驱结点的右孩子指针指向当前节点t98.if(t->lflag == 1)99. t->lchild = current;//现结点t的左孩子指针指向前驱结点100. }101. current = t;//让前驱结点为t为下一次执行函数做准备102. InThreading(t->rchild);//递归调用右子树进行线索化103. }104.}105.//检查if的==106.//遍历中序线索二叉树107.void InVisitThrtree(BiThrTree *t)108.{109.while(t != NULL)//大循环110. {111.while(t->lflag == 0)//小循环1;此循环第一次进行时首先要去找到最左节点112. t = t->lchild;113.if(t == NULL)114. exit(ERROR);115. printf("%c\t",t->data);116.while(t->rflag == 1 && t->rchild != NULL)//小循环2117. {118. t = t->rchild;119. printf("%c\t",t->data);120. }121. t = t->rchild;122./*123.两种情况:124. 1.如果t的右子树为空则t直接指向t的中序后继结点.125. 2.如果t的右子树不为空,即t->rflag为0,那么退出这个小循环2回到大循环中,再到小循环1中去找t的右子树的最左下的结点.126. */127. }128.}129.130.//将二叉树后序线索化(递归)131.void PostThreading(BiThrTree *t)132.{133.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数134. {135. PreThreading(t->lchild);136. PreThreading(t->rchild);137.if(t->lchild == NULL)138. t->lflag = 1;139.if(t->rchild == NULL)140. t->rflag = 1;141.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上1142.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL143. {144.if(current->rflag == 1)145. current->rchild = t;//前驱结点的右孩子指针指向当前节点t146.if(t->lflag == 1)147. t->lchild = current;//现结点t的左孩子指针指向前驱结点148. }149. current = t;//让前驱结点为t为下一次执行函数做准备150. }151.}152.//遍历后序线索二叉树153.void PostVisitThrtree(BiThrTree *t)154.{155.if(t)156. {157.while(t->lchild != NULL && t->lflag == 0)158. {159. t = t->lchild;//先遍历到最左边的节点160. }161. }162.}163.//主函数164.void main()165.{166. BiThrTree *t,*s;167. printf("\t\t请按先序序列输入二叉树(如:ABC@@DE@G@@F@@@#)\n\t\t");168. t = CreateBiThrTree();169. InThreading(t);170. printf("\t\t按中序遍历输出线索二叉树:\n\t\t");171. InVisitThrtree(t);172. printf("\n");173.//getchar();174.//getchar();175. fflush(stdin);//这个操作必须要进行,或者是进行上面注释的那两步操作,要不然176. printf("\t\t请按先序序列输入二叉树(如:ABC@@DE@G@@F@@@#)\n\t\t");177. s = CreateBiThrTree();178. PreThreading(s);179. printf("\t\t按前序遍历输出线索二叉树:\n\t\t");180. PreVisitThrtree(s);181.}7.测试图8.实验总结然对于这一节,主要是讨论线索二叉树的建立以及遍历,对于二叉树的建立,主要有五个部分构成,分别是data,lchild,rchild,lflag,rflag,而它与二叉树不同的地方就是多了lflag和rflag的判断,当当前节点的左节点为空时一定会指向它的前驱结点,当前驱节点的右节点为空时,让前驱结点的右指针域指向当前节点,这就是线索化,而对于前序中序后序的线索化本质都是一样的。
二叉树遍历(前中后序遍历,三种方式)
⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。
对应的LeetCode题⽬如下:,,,接下来以前序遍历来说明三种解法的思想,后⾯中序和后续直接给出代码。
⾸先定义⼆叉树的数据结构如下://Definition for a binary tree node.struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};前序遍历,顺序是“根-左-右”。
使⽤递归实现:递归的思想很简单就是我们每次访问根节点后就递归访问其左节点,左节点访问结束后再递归的访问右节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;helper(root,res);return res;}void helper(TreeNode *root, vector<int> &res){res.push_back(root->val);if(root->left) helper(root->left, res);if(root->right) helper(root->right, res);}};使⽤辅助栈迭代实现:算法为:先把根节点push到辅助栈中,然后循环检测栈是否为空,若不空,则取出栈顶元素,保存值到vector中,之后由于需要想访问左⼦节点,所以我们在将根节点的⼦节点⼊栈时要先经右节点⼊栈,再将左节点⼊栈,这样出栈时就会先判断左⼦节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;stack<TreeNode*> st;st.push(root);while(!st.empty()){//将根节点出栈放⼊结果集中TreeNode *t = st.top();st.pop();res.push_back(t->val);//先⼊栈右节点,后左节点if(t->right) st.push(t->right);if(t->left) st.push(t->left);}return res;}};Morris Traversal⽅法具体的详细解释可以参考如下链接:这种解法可以实现O(N)的时间复杂度和O(1)的空间复杂度。
数据结构入门-树的遍历以及二叉树的创建
数据结构⼊门-树的遍历以及⼆叉树的创建树定义:1. 有且只有⼀个称为根的节点2. 有若⼲个互不相交的⼦树,这些⼦树本⾝也是⼀个树通俗的讲:1. 树是有结点和边组成,2. 每个结点只有⼀个⽗结点,但可以有多个⼦节点3. 但有⼀个节点例外,该节点没有⽗结点,称为根节点⼀、专业术语结点、⽗结点、⼦结点、根结点深度:从根节点到最底层结点的层数称为深度,根节点第⼀层叶⼦结点:没有⼦结点的结点⾮终端节点:实际上是⾮叶⼦结点度:⼦结点的个数成为度⼆、树的分类⼀般树:任意⼀个结点的⼦结点的个数都不受限制⼆叉树:任意⼀个结点的⼦结点个数最多是两个,且⼦结点的位置不可更改⼆叉数分类:1. ⼀般⼆叉数2. 满⼆叉树:在不增加树层数的前提下,⽆法再多添加⼀个结点的⼆叉树3. 完全⼆叉树:如果只是删除了满⼆叉树最底层最右边的连续若⼲个结点,这样形成的⼆叉树就是完全⼆叉树森林:n个互不相交的树的集合三、树的存储⼆叉树存储连续存储(完全⼆叉树)优点:查找某个结点的⽗结点和⼦结点(也包括判断有没有⼦结点)速度很快缺点:耗⽤内存空间过⼤链式存储⼀般树存储1. 双亲表⽰法:求⽗结点⽅便2. 孩⼦表⽰法:求⼦结点⽅便3. 双亲孩⼦表⽰法:求⽗结点和⼦结点都很⽅便4. ⼆叉树表⽰法:把⼀个⼀般树转化成⼀个⼆叉树来存储,具体转换⽅法:设法保证任意⼀个结点的左指针域指向它的第⼀个孩⼦,右指针域指向它的兄弟,只要能满⾜此条件,就可以把⼀个⼀般树转化为⼆叉树⼀个普通树转换成的⼆叉树⼀定没有右⼦树森林的存储先把森林转化为⼆叉树,再存储⼆叉树四、树的遍历先序遍历:根左右先访问根结点,再先序访问左⼦树,再先序访问右⼦树中序遍历:左根右中序遍历左⼦树,再访问根结点,再中序遍历右⼦树后续遍历:左右根后续遍历左⼦树,后续遍历右⼦树,再访问根节点五、已知两种遍历求原始⼆叉树给定了⼆叉树的任何⼀种遍历序列,都⽆法唯⼀确定相应的⼆叉树,但是如果知道了⼆叉树的中序遍历序列和任意的另⼀种遍历序列,就可以唯⼀地确定⼆叉树已知先序和中序求后序先序:ABCDEFGH中序:BDCEAFHG求后序:这个⾃⼰画个图体会⼀下就可以了,⾮常简单,这⾥简单记录⼀下1. ⾸先根据先序确定根,上⾯的A就是根2. 中序确定左右,A左边就是左树(BDCE),A右边就是右树(FHG)3. 再根据先序,A左下⾯就是B,然后根据中序,B左边没有,右边是DCE4. 再根据先序,B右下是C,根据中序,c左下边是D,右下边是E,所以整个左树就确定了5. 右树,根据先序,A右下是F,然后根据中序,F的左下没有,右下是HG,6. 根据先序,F右下为G,然后根据中序,H在G的左边,所以G的左下边是H再来⼀个例⼦,和上⾯的思路是⼀样的,这⾥就不详细的写了先序:ABDGHCEFI中序:GDHBAECIF已知中序和后序求先序中序:BDCEAFHG后序:DECBHGFA这个和上⾯的思路是⼀样的,只不过是反过来找,后序找根,中序找左右树简单应⽤树是数据库中数据组织⼀种重要形式操作系统⼦⽗进程的关系本⾝就是⼀棵树⾯向对象语⾔中类的继承关系哈夫曼树六、⼆叉树的创建#include <stdio.h>#include <stdlib.h>typedef struct Node{char data;struct Node * lchild;struct Node * rchild;}BTNode;/*⼆叉树建⽴*/void BuildBT(BTNode ** tree){char ch;scanf("%c" , &ch); // 输⼊数据if(ch == '#') // 如果这个节点的数据是#说明这个结点为空*tree = NULL;else{*tree = (BTNode*)malloc(sizeof(BTNode));//申请⼀个结点的内存 (*tree)->data = ch; // 将数据写⼊到结点⾥⾯BuildBT(&(*tree)->lchild); // 递归建⽴左⼦树BuildBT(&(*tree)->rchild); // 递归建⽴右⼦树}}/*⼆叉树销毁*/void DestroyBT(BTNode *tree) // 传⼊根结点{if(tree != NULL){DestroyBT(tree->lchild);DestroyBT(tree->rchild);free(tree); // 释放内存空间}}/*⼆叉树的先序遍历*/void Preorder(BTNode * node){if(node == NULL)return;else{printf("%c ",node->data );Preorder(node->lchild);Preorder(node->rchild);}}/*⼆叉树的中序遍历*/void Inorder(BTNode * node){if(node == NULL)return;else{Inorder(node->lchild);printf("%c ",node->data );Inorder(node->rchild);}}/*⼆叉树的后序遍历*/void Postorder(BTNode * node){if(node == NULL)return;else{Postorder(node->lchild);Postorder(node->rchild);printf("%c ",node->data );}}/*⼆叉树的⾼度树的⾼度 = max(左⼦树⾼度,右⼦树⾼度) +1*/int getHeight(BTNode *node){int Height = 0;if (node == NULL)return 0;else{int L_height = getHeight(node->lchild);int R_height = getHeight(node->rchild);Height = L_height >= R_height ? L_height +1 : R_height +1; }return Height;}int main(int argc, char const *argv[]){BTNode * BTree; // 定义⼀个⼆叉树printf("请输⼊⼀颗⼆叉树先序序列以#表⽰空结点:");BuildBT(&BTree);printf("先序序列:");Preorder(BTree);printf("\n中序序列:");Inorder(BTree);printf("\n后序序列:");Postorder(BTree);printf("\n树的⾼度为:%d" , getHeight(BTree));return 0;}// ABC##DE##F##G##。
C语言实现创建二叉树,先序遍历、中序遍历、后序遍历输出
C语⾔实现创建⼆叉树,先序遍历、中序遍历、后序遍历输出# include <stdio.h># include <stdlib.h># include <string.h># include <iostream># define OK 0;# define ERROR -1;typedef int TElemType;typedef char DataType;typedef int Status;typedef struct BiNode {DataType data;//存⾃定义类型的值struct BiNode *lchild, *rchild;//左右⼩孩指针}BiNode,*BiTree;void CreatBiNode(BiNode **Node)//此处应注意传递的参数(⼆重指针){char data;scanf_s("%c", &data);*Node = (BiTree)malloc(sizeof(BiNode));if (data == '#'){*Node = NULL;}else if ((data != '#') && (*Node)){(*Node)->data = data;(*Node)->lchild = NULL;(*Node)->rchild = NULL;CreatBiNode(&(*Node)->lchild);CreatBiNode(&(*Node)->rchild);}}Status PreOrderTraverse(BiTree T) {if (T == NULL) {return OK;}else {printf("%c", T->data);PreOrderTraverse(T->lchild);PreOrderTraverse(T->rchild);}}Status InOrderTraverse(BiTree T) {if (T == NULL) {return OK;}else {InOrderTraverse(T->lchild);printf("%c", T->data);InOrderTraverse(T->rchild);}}Status PostOrderTraverse(BiTree T) {if (T == NULL) {return OK;}else {PostOrderTraverse(T->lchild);PostOrderTraverse(T->rchild);printf("%c", T->data);}}int main(){printf("先序输⼊⼆叉树(空结点⽤'#'表⽰):");BiTree T=NULL;CreatBiNode(&T);printf("先序遍历⼆叉树:");PreOrderTraverse(T);printf("\n中序遍历⼆叉树:");InOrderTraverse(T);printf("\n后序遍历⼆叉树:");PostOrderTraverse(T);system("pause");return 0;}解决思想:⼩⽣⽤的是递归创建⼆叉树,递归遍历⼆叉树,因为使⽤递归会⽐较简洁。
二叉树的遍历PPT-课件
4 、二叉树的创建算法
利用二叉树前序遍历的结果可以非常方便地生成给定的
二叉树,具体做法是:将第一个输入的结点作为二叉树的 根结点,后继输入的结点序列是二叉树左子树前序遍历的 结果,由它们生成二叉树的左子树;再接下来输入的结点 序列为二叉树右子树前序遍历的结果,应该由它们生成二 叉树的右子树;而由二叉树左子树前序遍历的结果生成二 叉树的左子树和由二叉树右子树前序遍历的结果生成二叉 树的右子树的过程均与由整棵二叉树的前序遍历结果生成 该二叉树的过程完全相同,只是所处理的对象范围不同, 于是完全可以使用递归方式加以实现。
void createbintree(bintree *t) { char ch; if ((ch=getchar())==' ') *t=NULL; else { *t=(bintnode *)malloc(sizeof(bintnode)); /*生成二叉树的根结点*/ (*t)->data=ch; createbintree(&(*t)->lchild); /*递归实现左子树的建立*/ createbintree(&(*t)->rchild); /*递归实现右子树的建立*/ }
if (s.top>-1) { t=s.data[s.top]; s.tag[s.top]=1; t=t->rchild; }
else t=NULL; }
}
7.5 二叉树其它运算的实现
由于二叉树本身的定义是递归的,因此关于二叉树的许多 问题或运算采用递归方式实现非常地简单和自然。 1、二叉树的查找locate(t,x)
(1)对一棵二叉树中序遍历时,若我们将二叉树严
格地按左子树的所有结点位于根结点的左侧,右子树的所
数据结构课程设计二叉树遍历C++语言
淮阴工学院实践报告数据结构课程设计设计题目:二叉树遍历系别:计算机工程学院专业:软件工程班级:软件1111学生姓名: 周淼学号: 1111315217起止日期: 2012年12月24日~2012年12月30日指导教师:寇海洲摘要:现代社会生活中,计算机扮演着重要角色,而随着计算机运行速度的不断加快,对数据的处理能力也日益增强,因此,程序所涉及的数据成爆发式增长。
随之而来的问题就是如何科学有效的对数据进行操作,使得计算机的时间和空间利用率最高。
针对这样的问题,我选择了二叉树对数据的各种操作作为我的课程设计主题,希望通过课程设计来提高对数据的处理能力,促进对数据结构课程的理解,在日后面向对象的程序设计中科学的规划数据结构。
在本次课程设计中,二叉树的建立使用了递归算法,遍历则同时使用了递归与非递归的算法,同时,在遍历算法的实现中使用了栈结构与队列结构,这大大方便了二叉树的遍历。
在前序、中序、后续遍历算法中,分别实现了递归与非递归算法,从实际应用中体验了递归这一算法的优越性。
关键词:二叉树建立,递归与非递归,遍历,栈,队列编号:47淮阴工学院软件工程专业数据结构课程设计答辩记录课题名称:二叉树的算法班级软件1111 学号1111315217 姓名周淼记录人:寇海洲2012 年12 月28日目录1需求分析 (6)1.1二叉树与树结构 (6)1.2面向对象的程序设计 (6)1.3二叉树遍历的应用 (6)1.4软件运行环境:Visual C++ 6.0版本 (6)2概要设计 (7)2.1 总体功能结构 (7)2.2数据结构部分设计 (7)2.2.1结点结构 (7)2.2.2 二叉树结构 (8)3详细设计 (13)3.1建立二叉树 (13)3.1.1功能描述 (13)3.1.2算法原理 (13)3.1.3 具体程序 (13)3.2 前序遍历 (14)3.2.1 功能原理 (14)3.2.2 算法原理 (14)3.2.3 具体程序 (14)3.3 中序遍历 (15)3.3.1 功能原理 (15)3.3.2 算法原理 (15)3.3.3 具体程序 (15)3.4 后序遍历 (16)3.4.1功能原理 (16)3.4.2 算法原理 (16)3.4.3 具体程序 (17)3.5层次序非递归遍历 (18)3.5.1 功能原理 (18)3.5.2 算法原理 (18)3.5.3 具体程序 (18)3.6 栈结构 (19)3.6.1 功能原理 (19)3.6.2算法原理 (19)3.6.3 具体程序 (19)3.7 队列结构 (20)3.7.1 功能原理 (20)3.7.2 算法原理 (20)3.7.3 具体程序 (20)4调试与操作说明 (21)致谢 (24)参考文献 (25)附录: (26)1需求分析1.1二叉树与树结构树结构的是建立在数据逻辑结构基础上的数据结构类型,二叉树则是树结构中最常见和使用最多的类型。
C语言 二叉树的建立,撤销与遍历
C语言二叉树的建立,撤销与遍历二叉树是一种特殊的树,每个节点只能有最多二个孩子节点,或者没有孩子节点。
建立,与撤销或遍历二叉树主要是靠递归的方法。
#include<stdio.h>#include<stdlib.h>typedef struct stud/*定义二叉树的结构,只有一个数据项,和两个孩子节点*/{char data;struct stud *left;struct stud *right;} bitree;void destroy(bitree **root)/*撤销二叉树,这里用的是递归和二级指针*/ {if(*root!=NULL&&(*root)->left!=NULL)/*当前结点与左子树不空,递归撤销左子树*/destroy(&(*root)->left);if(*root!=NULL&&(*root)->right!=NULL)/*当前结点与右子树不空,递归撤销右子树*/destroy(&(*root)->right);free(*root);/*左右子树都为空,撤销该节点,并递归撤销其上的所有节点*/ }void inititate(bitree **root)/*初始化二叉树的头结点,并分配空间*/ {*root=(bitree *)malloc(sizeof(bitree ));(*root)->left=NULL;(*root)->right=NULL;}bitree *insert_left(bitree *curr,char x)/*在左子树插入数据*/{bitree *s,*t;if(curr==NULL)return NULL;t=curr->left;/*保存当前左子树的数据*/s=(bitree *)malloc(sizeof(bitree));s->data=x;s->left=t;/*新结点指向原来的左子树*/s->right=NULL;curr->left=s;/*原来的节点指向新结点*/return curr->left;}bitree *insert_right(bitree *curr,char x)/*在这个节点的右子树插入数据*/{bitree *s,*t;if(curr==NULL)return NULL;t=curr->right;s=(bitree *)malloc(sizeof(bitree));s->data=x;s->left=NULL;s->right=t;curr->right=s;return curr->right;}bitree *delete_left(bitree *curr)/*删除当前结点的左子树*/{if(curr!=NULL&&curr->left!=NULL)destroy(&curr->left);/*删除左子树本身及其以后的所有节点*/curr->left=NULL;return curr;}bitree *delete_right(bitree *curr)/*删除右子树*/{if(curr!=NULL&&curr->right!=NULL)destroy(&curr->right);curr->right=NULL;return curr;}void preorder(bitree *root)/*递归先序遍历根节点*/ {if(root!=NULL){printf("%c ",root->data);preorder( root->left);preorder( root->right);}}void midorder(bitree *root)/*递归中序遍历根节点*/ {if(root!=NULL){midorder( root->left);printf("%c ",root->data);midorder(root->right);}}void postorder(bitree *root))/*递归后序遍历根节点*/ {if(root!=NULL){postorder(root->left);postorder( root->right);printf("%c ",root->data);}}bitree *search(bitree *root,char x))/*递归某一数值*/ {bitree *find=NULL;if(root!=NULL){if(root->data==x)find=root;else{find=search (root->left,x);)/*在左子树查找*/ if(find==NULL))/*左子树没有找到的话*/find=search (root->right,x);/*右子树找*/}}return find;}void main(){bitree *root,*s,*p,*find;int i,j,k;char c='E';inititate(&root);p=insert_left(root,'A');p=insert_left(p,'B');p=insert_left(p,'D');p=insert_right(p,'G');p=insert_right(root->left,'C');insert_left(p,'E');insert_right(p,'F');printf("前序遍历为\n");preorder(root->left);printf("\n中序遍历为\n");midorder(root->left);printf("\n后序遍历为\n");postorder(root->left);find=search(root->left,c);if(find)printf("这个元素%c在二叉树中\n",c);elseprintf("这个元素%c不在二叉树中\n",c);printf("撤销根节点的左子树为\n");delete_left(root->left);printf("\n前序遍历为\n");preorder(root->left);printf("\n中序遍历为\n");midorder(root->left);printf("\n后序遍历为\n");postorder(root->left);printf("\n撤销根节点的右子树为\n"); delete_right(root->left);printf("前序遍历为\n");preorder(root->left);printf("\n中序遍历为\n");midorder(root->left);printf("\n后序遍历为\n");postorder(root->left);destroy(&root);}。
二叉树的建立和遍历的实验报告
竭诚为您提供优质文档/双击可除二叉树的建立和遍历的实验报告篇一:二叉树遍历实验报告数据结构实验报告报告题目:二叉树的基本操作学生班级:学生姓名:学号:一.实验目的1、基本要求:深刻理解二叉树性质和各种存储结构的特点及适用范围;掌握用指针类型描述、访问和处理二叉树的运算;熟练掌握二叉树的遍历算法;。
2、较高要求:在遍历算法的基础上设计二叉树更复杂操作算法;认识哈夫曼树、哈夫曼编码的作用和意义;掌握树与森林的存储与便利。
二.实验学时:课内实验学时:3学时课外实验学时:6学时三.实验题目1.以二叉链表为存储结构,实现二叉树的创建、遍历(实验类型:验证型)1)问题描述:在主程序中设计一个简单的菜单,分别调用相应的函数功能:1…建立树2…前序遍历树3…中序遍历树4…后序遍历树5…求二叉树的高度6…求二叉树的叶子节点7…非递归中序遍历树0…结束2)实验要求:在程序中定义下述函数,并实现要求的函数功能:createbinTree(binTreestructnode*lchild,*rchild;}binTnode;元素类型:intcreatebinTree(binTreevoidpreorder(binTreevoidInorder(binTreevoidpostorder(binTreevoidInordern(binTreeintleaf(bi nTreeintpostTreeDepth(binTree2、编写算法实现二叉树的非递归中序遍历和求二叉树高度。
1)问题描述:实现二叉树的非递归中序遍历和求二叉树高度2)实验要求:以二叉链表作为存储结构3)实现过程:1、实现非递归中序遍历代码:voidcbiTree::Inordern(binTreeinttop=0;p=T;do{while(p!=nuLL){stack[top]=p;;top=top+1;p=p->lchild;};if(top>0){top=top-1;p=stack[top];printf("%3c",p->data);p=p->rchild;}}while(p!=nuLL||top!=0);}2、求二叉树高度:intcbiTree::postTreeDepth(binTreeif(T!=nuLL){l=postTreeDepth(T->lchild);r=postTreeDepth(T->rchil d);max=l>r?l:r;return(max+1);}elsereturn(0);}实验步骤:1)新建一个基于consoleApplication的工程,工程名称biTreeTest;2)新建一个类cbiTree二叉树类。
c++实现树(二叉树)的建立和遍历算法(一)(前序,中序,后序)
c++实现树(⼆叉树)的建⽴和遍历算法(⼀)(前序,中序,后序)最近学习树的概念,有关⼆叉树的实现算法记录下来。
不过学习之前要了解的预备知识:树的概念;⼆叉树的存储结构;⼆叉树的遍历⽅法。
⼆叉树的存储结构主要了解⼆叉链表结构,也就是⼀个数据域,两个指针域,(分别为指向左右孩⼦的指针),从下⾯程序1,⼆叉树的存储结构可以看出。
⼆叉树的遍历⽅法:主要有前序遍历,中序遍历,后序遍历,层序遍历。
(层序遍历下⼀篇再讲,本篇主要讲的递归法)下篇主要是,之后会有c++模板实现和。
如这样⼀个⼆叉树:它的前序遍历顺序为:ABDGHCEIF(规则是先是根结点,再前序遍历左⼦树,再前序遍历右⼦树)它的中序遍历顺序为:GDHBAEICF(规则是先中序遍历左⼦树,再是根结点,再是中序遍历右⼦树)它的后序遍历顺序为:GHDBIEFCA(规则是先后序遍历左⼦树,再是后序遍历右⼦树,再是根结点)如果不懂的话,可以参看有关数据结构的书籍。
1,⼆叉树的存储结构(⼆叉链表)//⼆叉树的⼆叉链表结构,也就是⼆叉树的存储结构,1个数据域,2个指针域(分别指向左右孩⼦)typedef struct BiTNode{ElemType data;struct BiTNode *lchild, *rchild;}BiTNode, *BiTree;2,⾸先要建⽴⼀个⼆叉树,建⽴⼆叉树必须要了解⼆叉树的遍历⽅法。
//⼆叉树的建⽴,按前序遍历的⽅式建⽴⼆叉树,当然也可以以中序或后序的⽅式建⽴⼆叉树void CreateBiTree(BiTree *T){ElemType ch;cin >> ch;if (ch == '#')*T = NULL; //保证是叶结点else{*T = (BiTree)malloc(sizeof(BiTNode));//if (!*T)//exit(OVERFLOW); //内存分配失败则退出。
二叉树的创建与遍历的实验总结
二叉树的创建与遍历的实验总结引言二叉树是一种重要的数据结构,在计算机科学中有着广泛的应用。
了解二叉树的创建和遍历方法对于数据结构的学习和算法的理解至关重要。
本文将对二叉树的创建和遍历进行实验,并总结相应的经验和思考。
二叉树的定义在开始实验之前,我们首先需要了解二叉树的定义和基本概念。
二叉树是一种每个节点最多拥有两个子节点的树形结构。
每个节点包含一个值和指向其左右子节点的指针。
根据节点的位置,可以将二叉树分为左子树和右子树。
创建二叉树二叉树的创建可以采用多种方法,包括手动创建和通过编程实现。
在实验中,我们主要关注通过编程方式实现二叉树的创建。
1. 递归方法递归是一种常用的创建二叉树的方法。
通过递归,我们可以从根节点开始,逐层创建左子树和右子树。
具体步骤如下:1.创建一个空节点作为根节点。
2.递归地创建左子树。
3.递归地创建右子树。
递归方法的代码实现如下所示:class TreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef create_binary_tree(values):if not values:return None# 使用队列辅助创建二叉树queue = []root = TreeNode(values[0])queue.append(root)for i in range(1, len(values)):node = TreeNode(values[i])# 当前节点的左子节点为空,则将新节点作为左子节点if not queue[0].left:queue[0].left = node# 当前节点的右子节点为空,则将新节点作为右子节点elif not queue[0].right:queue[0].right = node# 当前节点的左右子节点已经齐全,可以从队列中删除该节点queue.pop(0)# 将新节点添加到队列中,下一次循环时可以使用该节点queue.append(node)return root2. 非递归方法除了递归方法,我们还可以使用非递归方法创建二叉树。
二叉树的操作实验报告
二叉树的操作实验报告
实验报告:二叉树的操作
引言:
二叉树是计算机科学中最基础、最重要的数据结构之一,它不仅在算法设计与分析中被广泛应用,而且也在计算机系统和软件工程领域被广泛使用。
在这次实验中,我们将学习和实现二叉树的基本操作,包括二叉树的建立、遍历、查找和删除等。
实验过程:
1. 二叉树的建立
2. 二叉树的遍历
3. 二叉树的查找
4. 二叉树的删除
实验结果:
1. 建立一颗二叉树,根节点为A,左子树B,右子树C,B的左子树D,右子树E,C的左子树F,右子树G。
结构如下:
A
/ \
B C
/ \ / \
D E F G
2. 对上述二叉树先进行中序遍历:DBEAFCG,再进行前序遍历:ABDECFG,最后进行后序遍历:DEBFGCA。
3. 在上述二叉树中查找元素G,并输出其父节点元素C。
4. 删除上述二叉树中的元素F,再对其进行中序遍历,结果为DBEACG。
结论:
通过这次实验,我们掌握了二叉树的基本操作方法,对于理解和分析算法、编写系统和软件工程都具有重要的意义。
同时,在实践中我们也深刻地认识到了二叉树操作的复杂性和局限性,这需要我们在实际应用中加以考虑和综合利用,才能发挥其最大的价值和作用。
二叉树的遍历算法
二叉树的前序、后序的递归、非递归遍历算法学生姓名:贺天立指导老师:湛新霞摘要本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
在课程设计中,系统开发平台为Windows 2000,程序设计设计语言采用Visual C++,程序运行平台为Windows 98/2000/XP。
用除递归算法前序,后续,中序遍历树外还通过非递归的算法遍历树。
程序通过调试运行,初步实现了设计目标,并且经过适当完善后,将可以应用在商业中解决实际问题。
关键词程序设计;C++;树的遍历;非递归遍历1 引言本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
1.1课程设计的任务构造一棵树并输入数据,编写三个函数,非别是树的前序递归遍历算法、树的后序递归遍历算法、树的非递归中序遍历算法(这里的非递归以中序为例)。
在主程序中调用这三个函数进行树的遍历,观察用不同的遍历方法输出的数据的顺序和验证递归与非递归输出的数据是否一样。
1.2课程设计的性质由要求分析知,本设计主要要求解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
所以设计一个良好的前序、后序的递归、非递归遍历算法非常重要。
1.3课程设计的目的在程序设计中,可以用两种方法解决问题:一是传统的结构化程序设计方法,二是更先进的面向对象程序设计方法[1]。
利用《数据结构》课程的相关知识完成一个具有一定难度的综合设计题目,利用C语言进行程序设计。
巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
树的遍历分为前序、中序和后序,可以用递归算法实现树的三种遍历。
除了递归外还可以构造栈,利用出栈和入栈来实现树的前序遍历、中序遍历和后序遍历。
二叉树的遍历课程设计
《数据结构》课程设计报告设计题目:二叉树的遍历姓名:陈雷学号: 7专业:运算机科学与技术院系:运算机科学与技术班级: 1002指导教师:吴克力2012年 3 月1日摘要:本文主要说明如何实现二叉树的遍历。
这次二叉树的遍历基于二叉树的二叉链表存储结构。
遍历方式包括:前序遍历,中序遍历,后续遍历,层序遍历。
其中前序遍历和后续遍历采用非递归算法实现。
编程环境为VC++,除遍历操作外,还增加了求二叉树的深度,总结点数,每层结点数,和最近一路先人(LCA)问题的算法。
关键字:二叉树遍历非递归C++ LCAAbstract: This paper mainly describes how to implement binary tree traversal. The binary tree traversal is based on binary tree binary storage structure. Traversal method includes: preorder traversal,inorder traversal, postorder traversal, levelorder traversal. The former preorder traversal and postorder use of non - recursive algorithm. Programming environment is VC + +, in addition to traversal operation, also increased for solving the binary tree depth 、summary points and each layer of nodes, as well as the most recent common ancestor ( LCA ) algorithm.Keywords: binary tree traversal non-recursive C++ LCA目录一、问题描述 (4)问题描述:创建二叉树并遍历 (4)大体要求: (4)二、需求分析 (4)三、概要设计 (4)1.创建二叉树 (4)2.二叉树的非递归前序遍历示用意 (4)3.二叉树的后序非递归遍历示用意 (5)四、数据结构设计 (5)1.二叉树结点数据类型概念为: (5)2.二叉树数据类型概念为: (5)五、算法设计 (6)一、创建二叉树 (6)2、非递归前序遍历 (7)3、非递归后序遍历 (7)4、求二叉树的高度 (8)5、求二叉树每一层的结点数 (8)6、求两节点最近一路先人 (9)6、算法流程图 (10)六、程序测试与实现 (10)一、函数之间的挪用关系 (11)二、主程序 (11)3、测试数据 (12)4、测试结果 (12)七、调试分析 (14)八、碰到的问题及解决办法 (14)九、心得体会 (14)十、参考文献 (15)一、问题描述问题描述:创建二叉树并遍历大体要求:1、别离运用非递归的方式完成对二叉树的先序和后序遍历2、输出二叉树的高度3、输出每一层的结点数4、查找结点P 和结点Q的最近一路先人二、需求分析1.本程序的功能包括二叉树的成立,二叉树的递归遍历,二叉树的非递归遍历,查询二叉树的深度,查询每层的结点数,查找两个结点的最近一路先人,二叉树的打印。
基于C语言的遍历二叉树构造方法研究
的 问题 越 来 越 复杂 : 解 决 同 一 个 问 题 . 造 不 同 的 数 据 结 构 会 不 足 。 若 构 对 应 复 杂 程 度 不 同的 算 法 . 而设 计一 个 合 适 的 数 据 结 构 能 使 算 C + 言 仅 增 加 一 些 编 程 概 念 . 编 写 5 0 ~ 00 +语 在 0 0 1 0 0行 以下 法 的复 杂 程 度 大大 降 低 。 编程 人 员 在 实 践 中 体 会 到 : 好 一 种 高 的程 序 与 C语 言 相 比并 无 优 势 而 言 .反 而 不 如 C源 程 序 简 洁 。 学 级 语 言 仅 能 解 决三 成 所 遇 到 的 问题 .而 学 好 数 据 结 构 却 能 解 决 下 面 的 C源 程 序 Te 1 re . 按 现 行 通 用 指 针 函数 构 思 编 写 的建 c是 八 成 所 遇 到 的 问题 . 因此 . 软 件设 计 中 选 择 一 个 合 适 的数 据 结 立 与 中 序 遍 历 一 棵 二 叉 树 ; 输 人 为 一 串字 符 , 立 二 叉 树后 , 在 其 建 构 越 发 显 得 重要 经 过 中序 线 性 遍 历 搜 索 、 出为 按 字 典 大 小 顺 序 排 列 的 字 符 串 输 在 管 理 科 学 领 域 中 .很 多 问 题 都 可 以 转 化 为 树 Te re型 结 由 于这 不是 一 个 递 归 程 序 . 们在 静 态 阅读 和 比较 后 . 我 就会 感 觉 构 , 多叉 树又 都 可 以转 化 为 一 棵 等 价 的二 叉 树 B— re 而 iTe 。在 这 到不 如 本 文 第 3部 分 的递 归 函 数程 序 T e . 构 思清 晰 re c
上 面 提 到二 叉 树 是 递 归定 义 的 .如 同解 递 归 函数 的典 型 例 题 ” 诺 塔 ” 样 . 叉 树 的建 立 过 程 只有 使 用 递 归 算 法 才 能 达 汉 一 二 到 最 完 美 。 Psa语 言 中的 形 式 参 数 有 赋 值 和变 量 两 种 . 中 在 ac l 其 变 参传 递 的是 地 址 。 二叉 树 中根 指 针 的 内容 ( 根 地 址 1 空 二 而 即 从 叉 树 到 有一 个 根 结 点 的 二叉 树 是 变 化 的 .必 须 使 用 变量 参 数 传 递 地 址 功 能来 修 改 这个 根结 点 的 地 址 值 。在 P sa 语 言 中变 量 acl 参 数 可 以很 自然 地 编 写使 用 递 归 函数 建 立 二 叉 树 的 程 序 而 这 个 源 程 序 比较 简 洁 、 于 静 态 阅读 和 进 行 教 学 分 析 . 此 使 用 递 易 因 归 函数 建 立 与遍 历 二叉 树 是 数 据 结 构 中 的经 典 算 法 本 文 第 五 部 分 C语 言 源 程 序 Te. 通 过 经 典 的 P sa语 言 建 立 二 又 树 re c是 acl 源 程 序 清单 逐 句 翻 译 过来 .由 于可 以按 照 不 同 编 程 语 言 的 语 法 规 则 逐 句进 行 对 照 和参 考 .故 下 面 省 略 了 P s a 语 言 的 源 程 序 ac l
用C语言编写二叉树的建立与遍历
用C语言编写二叉树的建立与遍历1.对题目要有需求分析在需求分析中,将题目中要求的功能进行叙述分析,并且设计解决此问题的数据存储结构,设计或叙述解决此问题的算法。
给出实现功能的一组或多组测试数据,程序调试后,将按照此测试数据进行测试的结果列出来。
如果程序不能正常运行,写出实现此算法中遇到的问题和改进方法;2.对题目要有相应的源程序源程序要按照写程序的规则来编写。
要结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。
(注释量占总代码的四分之一)程序能够运行,要有基本的容错功能。
尽量避免出现操作错误时出现死循环;3.最后提供的主程序可以象一个应用系统一样有主窗口,通过主菜单和分级菜单调用课程设计中要求完成的各个功能模块,调用后可以返回到主菜单,继续选择其他功能进行其他功能的选择。
二叉树的建立与遍历[问题描述]建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。
[基本要求]从键盘接受输入,以二叉链表作为存储结构,建立二叉树,并对其进行遍历(先序、中序、后序),将遍历结果打印输出。
以下是我的数据结构实验的作业:肯定好用,里面还包括了统计树的深度和叶子数!记住每次做完一个遍历还要重新输入你的树哦!#include "stdio.h"#include "string.h"#define NULL 0typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;BiTree Create(BiTree T){char ch;ch=getchar();if(ch=='#')T=NULL;else{if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))printf("Error!");T->data=ch;T->lchild=Create(T->lchild);T->rchild=Create(T->rchild); }return T;}void Preorder(BiTree T){if(T){printf("%c",T->data); Preorder(T->lchild); Preorder(T->rchild);}}int Sumleaf(BiTree T){int sum=0,m,n;if(T){if((!T->lchild)&&(!T->rchild)) sum++;m=Sumleaf(T->lchild);sum+=m;n=Sumleaf(T->rchild);sum+=n;}return sum;}void zhongxu(BiTree T){if(T){zhongxu(T->lchild);printf("%c",T->data); zhongxu(T->rchild);}}void houxu(BiTree T){if(T){houxu(T->lchild);houxu(T->rchild);printf("%c",T->data);}}int Depth(BiTree T){int dep=0,depl,depr;if(!T) dep=0;else{depl=Depth(T->lchild);depr=Depth(T->rchild);dep=1+(depl>depr?depl:depr);}return dep;}main(){BiTree T;int sum,dep;T=Create(T);Preorder(T);printf("\n");zhongxu(T);printf("\n");houxu(T);printf("\n");sum=Sumleaf(T);printf("%d",sum);dep=Depth(T);printf("\n%d",dep);}在Turbo C的环境下,先按Ctrl+F9运行程序,此时就是建立二叉树的过程,例如输入序列ABC##DE#G##F###(其中的“#”表示空,并且输入过程中不要加回车,因为回车也有对应的ASCII码,是要算字符的,但是输入完之后可以按回车退出),然后再按ALT+F5显示用户界面,这时候就能够看到结果了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
judge ( p1 ); /*用递归算法将输入数据信息转为线性字符串*/
cout<<endl<<"输出转换的线性字符串: "<<endl;
cout<<a<<endl<<endl;
/*------------------------------------------遍历-----------------------------------*/
void postorder (leafnode* T); /*声明后序遍历函数*/
char a[100];
int k=1;
int s=0;
inform *p;
void main()
{
/*-------------------------------按格式输入信息-----------------------------------*/
int n;
cout<<"请输入二叉树内容:第一行为节点总数n ,后面的n行是节点的具体形式:"<<endl;
cout<<"n= ";
cin>>n;
p=(inform* )malloc( n*sizeof(inform) ); /*开辟的一个叶子结构体型的指针数组*/
#include <iostream.h>
#include <stdlib.h>
struct inform /*建立输入信息结构体inform*/
{ char data;
int l;
int r;
int signl; /*作为标记的signl,signr*/
else (p+i)->signl= 0;
if((p+i)->r !=-1) (p+se (p+i)->signr= 0;
}
/*--------------------------------------------------------------------------------------------*/
void postorder (leafnode* T)
{
if(T)
{
postorder(T->lchild);
postorder(T->rchild);
cout<<T->leaf;
}
}
void judge ( inform* ps );
leafnode* creatree(); /*声明二叉树的建立函数*/
void preorder (leafnode* T); /*声明先序遍历函数*/
void inorder (leafnode* T); /*声明中序遍历函数*/
leafnode* T;
T= creatree();
/*先续遍历二叉树*/
cout<<"先序遍历二叉树: "<<endl;
preorder( T );
cout<<endl<<"中序遍历二叉树: "<<endl;
inorder ( T );
cout<<endl<<"后序遍历二叉树: "<<endl;
{
char ch;
leafnode *t;
ch= a[s];
s++;
if(ch=='@')
{
t=NULL;
}
else
{
t=(leafnode* )malloc(sizeof(leafnode));
t->leaf=ch;
t->lchild=creatree();
inform *p1; p1=p;
for(int i=0; i<n; i++)
{
cin>>(p+i)->data>>(p+i)->l>>(p+i)->r;
if((p+i)->l != -1) (p+i)->signl=1; /*用signl signr 的0,1标示输入的信息中是否有左或右孩子*/
{
a[k]='@';
k++;
}
else
{
b = p+(ps->r );
a[k] = b->data;
k++;
judge(b);
}
}
leafnode* creatree() /*建立二叉树函数*/
int signr;
};
struct leafnode /*建立叶子节点结构体*/
{
char leaf;
leafnode* lchild;
leafnode* rchild;
};
void print(inform* ps, int n);
t->rchild=creatree();
}
return t;
}
/*先序遍历的递归函数*/
void preorder (leafnode* T)
{
if(T)
{
cout<<T->leaf;
preorder(T->lchild);
preorder(T->rchild);
postorder( T );
cout<<endl<<endl;
}
/*------------------------------------------函数定义-------------------------------*/
void judge( inform* ps ) /*用函数的递归来将输入的信息转化为线性的数组*/
{
inform* b;
if (ps->signl==0)
{
a[k]='@';
k++;
}
else
{
b = p+(ps->l);
a[k] = b->data;
k++;
judge(b);
}
if ((ps->signr) == 0)
}
}
/*中序遍历的递归函数*/
void inorder (leafnode* T)
{
if(T)
{
inorder(T->lchild);
cout<<T->leaf;
inorder(T->rchild);
}
}
/*后序遍历的递归函数*/