二叉树的创建、遍历

二叉树的创建。这里采用最简单的情况,创建完全二叉树,用数组来保存:

 1 struct TreeNode
 2 {
 3     int val;
 4     TreeNode *left, *right;
 5     TreeNode(int x): val(x), left(NULL), right(NULL) {};
 6 };
 7
 8 void CreatTree(TreeNode *root, int idx, int A[], int n)   //root结点已分配,idx为根结点的编号
 9 {
10     if(2 * idx <= n)   //左儿子
11     {
12         root->left = new TreeNode(A[2 * idx - 1]);
13         CreatTree(root->left, 2 * idx, A, n);
14     }
15     if(2 * idx + 1 <= n)  //右儿子
16     {
17         root->right = new TreeNode(A[2 * idx]);
18         CreatTree(root->right, 2 * idx + 1, A, n);
19     }
20 }

二叉树的销毁:

1 void DestroyTree(TreeNode *root)
2 {
3     if(root == NULL)
4         return;
5     DestroyTree(root->left);    //先递归删除子树
6     DestroyTree(root->right);
7     delete root;
8 }

二叉树的层次遍历:

 1 //层次遍历
 2 void BreadthFirstPrint(TreeNode *root) //BFS, 用队列
 3 {
 4     if(root == NULL)
 5         return;
 6     queue<TreeNode *> que;
 7     que.push(root);
 8
 9     TreeNode *current = NULL;
10     while(!que.empty())
11     {
12         current = que.front();
13         que.pop();
14
15         cout << current->val << ‘ ‘;
16
17         if(current->left != NULL)
18             que.push(current->left);
19         if(current->right != NULL)
20             que.push(current->right);
21     }
22 }

二叉树的递归遍历:

 1 //先序遍历,递归
 2 void PreorderRe(TreeNode *root)
 3 {
 4     if(root == NULL)
 5         return;
 6     cout << root->val << ‘ ‘;
 7     PreorderRe(root->left);
 8     PreorderRe(root->right);
 9 }
10
11 //中序遍历,递归
12 void InorderRe(TreeNode *root)
13 {
14     if(root == NULL)
15         return;
16     InorderRe(root->left);
17     cout << root->val << ‘ ‘;
18     InorderRe(root->right);
19 }
20
21 //后序遍历,递归版
22 void PostorderRe(TreeNode *root)
23 {
24     if(root == NULL)
25         return;
26     PostorderRe(root->left);
27     PostorderRe(root->right);
28     cout << root->val << ‘ ‘;
29 }

二叉树的非递归遍历,用栈:

 1 //先序遍历,非递归,用栈;也是DFS算法
 2 void PreorderStk(TreeNode *root)
 3 {
 4     if(root == NULL)
 5         return;
 6     stack<TreeNode *> stk;
 7     stk.push(root);
 8
 9     TreeNode *current = NULL;
10     while(!stk.empty())
11     {
12         current = stk.top();
13         stk.pop();
14
15         cout << current->val << ‘ ‘;
16
17         if(current->right != NULL)
18             stk.push(current->right);
19         if(current->left != NULL)
20             stk.push(current->left);
21     }
22 }
23
24 //中序遍历,用栈,非递归
25 void InorderStk(TreeNode *root)
26 {
27     if(root == NULL)
28         return;
29     stack<TreeNode *> stk;
30     stk.push(root);
31
32     TreeNode *current = root->left;
33     while(!stk.empty() || current != NULL)  //中序遍历,左子树访问完后栈为空,所以同时检测current,此时它指向右子树根
34     {
35         if(current != NULL)     //向左遍历到底
36         {
37             stk.push(current);
38             current = current->left;
39         }
40         else    //左子树为空,访问元素后遍历其右子树
41         {
42             cout << stk.top()->val << ‘ ‘;
43             current = stk.top()->right;
44             stk.pop();
45         }
46     }
47 }
48
49 //后序遍历,非递归版,用栈
50 void PostorderStk(TreeNode *root)
51 {
52     stack<TreeNode *> ndStk;
53     TreeNode *cur = root, *prev = NULL;     //维持一个prev指针,指向上一次访问的结点
54
55     while(cur != NULL)      //先向左遍历到底,入栈
56     {
57         ndStk.push(cur);
58         cur = cur->left;
59     }
60
61     while(!ndStk.empty())
62     {
63         cur = ndStk.top();
64         if(cur->right == prev)  //右子树的根已访问,说明右子树访问完;或者右子树为空,则访问当前结点
65         {
66             cout << cur->val << ‘ ‘;
67             ndStk.pop();
68             prev = cur;
69         }
70         else    //访问右子树
71         {
72             cur = cur->right;
73             while(cur != NULL)  //与处理根节点时的情况相同,向左遍历到底入栈,prev赋空值
74             {
75                 ndStk.push(cur);
76                 cur = cur->left;
77             }
78             prev = NULL;
79         }
80     }//while
81 }

二叉树的非递归遍历,O(1)空间,Morris遍历:

  1 //先序遍历,非递归,O(1)空间。Morris遍历
  2 void PreorderMrs(TreeNode *root)
  3 {
  4     TreeNode *p = root;
  5     while(p != NULL)
  6     {
  7         if(p->left != NULL)   //找中序遍历的前驱结点
  8         {
  9             TreeNode *tmp = p->left;
 10             while(tmp->right != NULL && tmp->right != p)
 11                 tmp = tmp->right;
 12             if(tmp->right == NULL)  //前驱还未做标记,说明当前结点还没访问
 13             {
 14                 tmp->right = p;     //标记前驱结点,使其右儿子为当前结点
 15                 cout << p->val << ‘ ‘;
 16                 p = p->left;        //访问当前节点后访问左子树
 17             }
 18             else                    //前驱已做标记,说明当前结点与左子树已访问过
 19             {
 20                 tmp->right = NULL;
 21                 p = p->right;
 22             }
 23         }
 24         else        //左子树为空,访问当前节点后访问右子树
 25         {
 26             cout << p->val << ‘ ‘;
 27             p = p->right;
 28         }
 29     }
 30 }
 31
 32 //中序遍历,非递归,O(1)空间。Morris遍历。
 33 void InorderMrs(TreeNode *root)
 34 {
 35     TreeNode *p = root;
 36     while(p != NULL)
 37     {
 38         if(p->left != NULL)
 39         {
 40             TreeNode *tmp = p->left;
 41             while(tmp->right != NULL && tmp->right != p)
 42                 tmp = tmp->right;
 43             if(tmp->right == NULL)
 44             {
 45                 tmp->right = p;
 46                 p = p->left;
 47             }
 48             else
 49             {
 50                 cout << p->val << ‘ ‘;      //和先序Morris的唯一不同点,访问元素的位置不同。当左子树访问完之后再访问当前结点。
 51                 p = p->right;
 52                 tmp->right = NULL;
 53             }
 54         }
 55         else
 56         {
 57             cout << p->val << ‘ ‘;
 58             p = p->right;
 59         }
 60     }
 61 }
 62
 63 //后序遍历,非递归,O(1)空间。Morris遍历。需要两个辅助函数
 64 void reverse(TreeNode *start, TreeNode *stop)
 65 {
 66     TreeNode *prev = start, *cur = start->right, *next;
 67     while(prev != stop)
 68     {
 69         next = cur->right;
 70         cur->right = prev;
 71         prev = cur;
 72         cur = next;
 73     }
 74 }
 75 void printReverseList(TreeNode *start, TreeNode *stop)
 76 {
 77     TreeNode *p = stop;
 78     reverse(start, stop);
 79     while(true)
 80     {
 81         cout << p->val << ‘ ‘;
 82         if(p == start)
 83             break;
 84         p = p->right;
 85     }
 86     reverse(stop, start);
 87 }
 88 void PostorderMrs(TreeNode *root)
 89 {
 90     TreeNode dummy(-1), *p = &dummy;
 91     dummy.left = root;  //新建一个结点,把root作为左儿子,方便统一处理
 92
 93     while(p != NULL)
 94     {
 95         if(p->left != NULL)     //找中序遍历的前驱结点
 96         {
 97             TreeNode *tmp = p->left;
 98             while(tmp->right != NULL && tmp->right != p)
 99                 tmp = tmp->right;
100             if(tmp->right == NULL)
101             {
102                 tmp->right = p;
103                 p = p->left;
104             }
105             else
106             {
107                 printReverseList(p->left, tmp); //与中序遍历的不同点,逆序输出当前结点的左儿子到前驱之间的路径
108
109                 tmp->right = NULL;
110                 p = p->right;
111             }
112         }
113         else
114         {
115             p = p->right;
116         }
117     }//while
118 }

二叉树的创建、遍历,布布扣,bubuko.com

时间: 2024-08-02 06:40:44

二叉树的创建、遍历的相关文章

二叉树基本操作--创建,三种遍历,叶子节点

虽然二叉树的操作很常见,但是认真写写熟悉很重要,特别是typedef, CreateBiTree(BiTNode** T)指针的操作等等,还有就是创建方法,去实际输入值就知道其中的妙处,为-1时为空节点. #include <iostream> using namespace std; //节点的定义 typedef struct BTNode { int data; BTNode* rChild; BTNode* lChild; }BiTNode, *BiTree; //二叉树的创建,先序创

算法实验-二叉树的创建和前序-中序-后序-层次 遍历

对于二叉树的创建我是利用先序遍历的序列进行创建 能够对于树节点的内容我定义为char型变量 '0'为空,即此处的节点不存在 头文件 Tree.h //链式二叉树的头文件 #pragma once #include<iostream> #include<queue> using namespace std; class BinaryTreeNode { public: char data; BinaryTreeNode *leftChild,*rightChild; BinaryTr

二叉树的创建和四种遍历(前序、先序、后序、层次、结点的层数、深度、叶子数等)—java描述

二叉树的创建和四种遍历(前序.先序.后序.层次.结点的层数.深度.叶子数等)—java描述 package javab; //树的结点类 public class TreeNode { String data; TreeNode leftChild,rightChild,next; public TreeNode(String data){ this.data=data; } public TreeNode(String data,TreeNode left,TreeNode right){ l

数据结构与算法第10周作业——二叉树的创建和遍历算法

一.二叉树的创建算法(递归方式) 二.二叉树的先序.中序和后序遍历算法 #include<stdio.h>#include<stdlib.h>typedef struct TNode{ struct TNode *lchild; int data; struct TNode *rchild;}TNode,*BTree;void createBiTree(BTree &T){ char x; scanf("%d",&x); if(x!=0) { T

二叉树的创建与遍历

#include<iostream>using namespace std; typedef char ELEMTYPE; //二叉链表typedef struct BiTNode{ ELEMTYPE data; struct BiTNode *lChild; struct BiTNode *rChild; }BiTNode,*BiTPtr; //创建二叉树,使用前序遍历的方式输入数据void CreateBiTree(BiTPtr *T){ char c; scanf("%c&qu

Java实现二叉树的创建、递归/非递归遍历

近期复习数据结构中的二叉树的相关问题,在这里整理一下 这里包含: 1.二叉树的先序创建 2.二叉树的递归先序遍历 3.二叉树的非递归先序遍历 4.二叉树的递归中序遍历 5.二叉树的非递归中序遍历 6.二叉树的递归后序遍历 7.二叉树的非递归后序遍历 8.二叉树的层次遍历 这里感谢博客http://blog.csdn.net/skylinesky/article/details/6611442的指导 /**二叉树的结点定义*/ class Node<T>{ private T value; pr

【数据结构之二叉树】二叉树的创建、遍历等操作

二叉树的基本操作: 1.创建二叉树 2.销毁二叉树 3.遍历二叉树:1)前序遍历 2)中序遍历 3)后序遍历 4)层次遍历 4.搜索二叉树 5.删除子叶 6.插入子叶 7.获取左/右子叶的值 8.获取树深度 9.获取叶子结点数 1.创建二叉树 这里创建的是链式存储结构的二叉树,包含数据域,左右两结点的指针域:在读取创建树时,以#代替空格,输入格式的规范为:以前序遍历的顺序输入,如果该结点的左子叶为空,则输入#,以此类推: e.g: -  +         \ a    *    e    f 

Java实现二叉树的创建和遍历操作(有更新)

博主强烈建议跳过分割线前面的部分,直接看下文更新的那些即可. 最近在学习二叉树的相关知识,一开始真的是毫无头绪.本来学的是C++二叉树,但苦于编译器老是出故障,于是就转用Java来实现二叉树的操作.但是二者原理是一致的,而且实现的方式也是大同小异! 下面就让我们来看看代码吧. 1.首先我们需要创建一个二叉树的节点类,便于我们对树的操作,当然了,你也可以在二叉树类的内部将节点类声明为内部类,但是这样会降低操作的灵活性.我才用的是单独创建一个BinaryTreeNode类,代码如下: package

二叉树 二叉树的性质 存储结构 遍历二叉树 C实现二叉树的创建和遍历 线索二叉树

定义 二叉树(binary tree)是n(n>=0)个结点的有限集合,该集合为空集合称为空二叉树,或者有一个根结点和两棵互不相交的,分别称为树根结点的左孩子树和右孩子树组成. 二叉树的特点 每个结点最多有两棵子树,所以二叉树总没有度大于2的结点 左子树和右子树是有顺序的,次数不能任意颠倒 即使树中某结点只有一棵子树,也要区分是左子树还是右子树 特殊的二叉树 1. 斜树 所有的结点都只有左子树的二叉树称为左斜树; 所有的结点都只有右子树的二叉树称为右斜树; 这两者统称为斜树 2. 满二叉树 在一