二叉树的链式实现

二叉树的定义见:二叉树实现:公式化描述

二叉树最常用的描述方法是用链表或指针。每个元素都用一个有两个指针域的节点表示,这两个域为 L e f t C h i l d和R i g h t C h i d。除此两个指针域外,每个节点还有一个 d a t a域。
二叉树的边可用一个从父节点到子节点的指针来描述。指针放在父节点的指针域中。因为包括个元素的二叉树恰有 n- 1 条边,因此将有2n- (n- 1 ) =n+ 1 个指针域没有值,这些域被置为0。

节点类:

 1 template<class T>
 2 class BinaryTreeNode
 3 {
 4     friend class BinaryTree<T>;
 5 public:
 6     //构造函数
 7     BinaryTreeNode(){ LeftChild = RightChild = 0; }
 8     BinaryTreeNode(const T& e){ data = e; LeftChild = RightChild = 0; }
 9     BinaryTreeNode(const T& e, BinaryTreeNode *l, BinaryTreeNode *r)
10     {
11         data = e;
12         LeftChild = l;
13         RightChild = r;
14     }
15 private:
16     T data;
17     BinaryTreeNode<T> *LeftChild;//左子树
18     BinaryTreeNode<T> *RightChild;//右子树
19 };

二叉树:

 1 template<class T>
 2 class BinaryTree
 3 {
 4 public:
 5     BinaryTree(){ root = NULL;
 6     }
 7
 8     //复制构造函数
 9     BinaryTree(const BinaryTree<T> &t);
10     ~BinaryTree(){};
11     bool IsEmpty() const{ return root == NULL };
12     bool Root(T& x)const;//获取根节点值
13     void MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right);//创建二叉树
14     void BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right);//分拆二叉树
15     void PreOrder(void (*Visit)(BinaryTreeNode<T> *u))//前序遍历
16     {
17         PreOrder(Visit, root);
18     }
19     void InOrder(void(*Visit)(BinaryTreeNode<T> *u))const//中序遍历
20     {
21         InOrder(Visit, root);
22     }
23     void PostOrder(void(*Visit)(BinaryTreeNode<T> *u))const//后序遍历
24     {
25         PostOrder(Visit, root);
26     }
27
28     BinaryTreeNode<T>* CopyTree(const BinaryTreeNode<T>* t);//复制树
29
30     void LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const;//层序遍历    //各种遍历输出
31     void PreOutput()const;
32     void InOutput()const;
33     void PostOutput()const;
34     void LevelOutput()const;
35     void Delete();
36     int Height()const//获取树的高度
37     {
38         return Height(root);
39     }
40
41     int Size();//树的节点数
42 private:
43     BinaryTreeNode<T> *root;//根节点
44     void PreOrder(void (*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t);
45     void InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const;
46     void PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const;
47     int Height(BinaryTreeNode<T> *t)const;
48
49
50     static void output(BinaryTreeNode<T> *t)
51     {
52         std::cout << t->data << ‘ ‘;
53     }
54
55     static void freeNode(BinaryTreeNode<T> *t)
56     {
57         delete t;
58         t = NULL;
59     }
60
61     static void ctsize(BinaryTreeNode<T> *t)
62     {
63         ++count;
64     }
65
66 };
  1 template<class T>
  2 BinaryTreeNode<T>* BinaryTree<T>::CopyTree(const BinaryTreeNode<T>* t)
  3 {
  4     if (t)
  5     {
  6         BinaryTreeNode<T>* lchild = CopyTree(t->LeftChild);
  7         BinaryTreeNode<T>* rchild = CopyTree(t->RightChild);
  8         root = new BinaryTreeNode<T>(t->data, lchild, rchild);
  9     }
 10
 11     return root;
 12 }
 13
 14 template<class T>
 15 BinaryTree<T>::BinaryTree(const BinaryTree<T> &t)
 16 {
 17     root = CopyTree(t.root);
 18 }
 19
 20
 21
 22 template<class T>
 23 int BinaryTree<T>::Size()
 24 {
 25     count = 0;
 26     PreOrder(ctsize);
 27     return count;
 28 }
 29
 30 template<class T>
 31 int BinaryTree<T>::Height(BinaryTreeNode<T> *t)const
 32 {
 33     if (!t)
 34     {
 35         return 0;
 36     }
 37
 38     int ll = Height(t->LeftChild);
 39     int lr = Height(t->RightChild);
 40
 41     if (ll > lr)
 42     {
 43         return ++ll;
 44     }
 45     else
 46         return ++lr;
 47 }
 48
 49 template<class T>
 50 bool BinaryTree<T>::Root(T& x) const
 51 {
 52     if (root)
 53     {
 54         x = root->data;
 55         return true;
 56     }
 57     return false;
 58 }
 59 //当left和right以及this二叉树有重复时,利用拷贝构造函数复制一部分,以免左右子树指向同一个而引发错误
 60 template<class T>
 61 void BinaryTree<T>::MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right)
 62 {
 63     if (&left==&right&&this==&left)
 64     {
 65         BinaryTree<T> newTree = right;
 66         BinaryTree<T> newTree2 = left;
 67         root = new BinaryTreeNode<T>(element, newTree2.root, newTree.root);
 68     }
 69     else if (&left==&right)
 70     {
 71         BinaryTree<T> newTree = right;
 72         root = new BinaryTreeNode<T>(element, left.root, newTree.root);
 73     }
 74     else if (this==&left||this==&right)
 75     {
 76         BinaryTree<T> newTree = *this;
 77         root = new BinaryTreeNode<T>(element, left.root, newTree.root);
 78     }
 79     else
 80     root = new BinaryTreeNode<T>(element, left.root, right.root);
 81
 82     left.root = right.root = NULL;
 83 }
 84
 85 template<class T>
 86 void BinaryTree<T>::BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right)
 87 {
 88     if (root==NULL)
 89     {
 90         std::cerr << "树为空,不能拆分" << std::endl;
 91         return;
 92     }
 93
 94     BinaryTree<T> newTree = *this;
 95     element = newTree.root->data;
 96     left.root = newTree.root->LeftChild;
 97     right.root = newTree.root->RightChild;
 98
 99     delete root;
100     root = NULL;
101 }
102
103 template<class T>
104 void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)
105 {
106     if (t)
107     {
108         Visit(t);
109         PreOrder(Visit, t->LeftChild);
110         PreOrder(Visit, t->RightChild);
111     }
112 }
113
114 template<class T>
115 void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const
116 {
117     if (t)
118     {
119         InOrder(Visit, t->LeftChild);
120         Visit(t);
121         InOrder(Visit, t->RightChild);
122     }
123 }
124
125 template<class T>
126 void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const
127 {
128     if (t)
129     {
130         PostOrder(Visit, t->LeftChild);
131         PostOrder(Visit, t->RightChild);
132         Visit(t);
133     }
134 }
135
136 template<class T>
137 void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const
138 {
139     LinkedQueue<T> Q;
140     BinaryTreeNode<T> *t = root;
141     while (t)
142     {
143         Visit(t);
144         if (t->LeftChild)
145         {
146             Q.Add(t->LeftChild);
147         }
148         if (t->RightChild)
149         {
150             Q.Add(t->RightChild);
151         }
152
153         if (Q.IsEmpty())
154         {
155             return;
156         }
157         Q.Delete(t);
158     }
159 }
160
161 template<class T>
162 void BinaryTree<T>::PreOutput()const
163 {
164     PreOrder(output, root);
165 }
166
167 template<class T>
168 void BinaryTree<T>::InOutput()const
169 {
170     InOrder(output, root);
171 }
172
173 template<class T>
174 void BinaryTree<T>::PostOutput()const
175 {
176     PostOrder(output, root);
177 }
178
179 template<class T>
180 void BinaryTree<T>::LevelOutput()const
181 {
182     LevelOutput(output, root);
183 }
184
185 template<class T>
186 void BinaryTree<T>::Delete()
187 {
188     PostOrder(freeNode, root);
189     root = NULL;
190 }

几个操作的解释:

前三种遍历可以用递归完成,层次调用则利用队列

删除:

要删除一棵二叉树,需要删除其所有节点。可以通过后序遍历在访问一个节点时,把其删除。也就是说先删除左子树,然后右子树,最后删除根。

计算高度:

通过进行后序遍历,可以得到二叉树的高度。首先得到左子树的高度 h l,然后得到右子树的高度h r。此时,树的高度为:m a x { h l, hr} + 1

简单测试:

 1 #include<iostream>
 2 #include "binaryTree.h"
 3
 4 int countx = 0;
 5 BinaryTree<int> a, x, y, z;
 6
 7 template<class T>
 8 void ct(BinaryTreeNode<T> *t)
 9 {
10     ++countx;
11 }
12
13 void main(void)
14 {
15     y.MakeTree(1, a, a);
16     z.MakeTree(2, y, y);
17     x.MakeTree(3, y, z);
18     y.MakeTree(4, x, a);
19     y.PreOrder(ct);
20
21     std::cout << countx << std::endl;
22     std::cout << y.Height() << std::endl;
23     std::cout << y.Size() << std::endl;
24     y.Delete();
25     std::cout << y.Height() << std::endl;
26     std::cout << y.Size() << std::endl;
27 }

时间: 2024-11-10 10:21:12

二叉树的链式实现的相关文章

数据结构:二叉树的链式存储

数据结构:二叉树的链式存储(C语言版) 1.写在前面 二叉树同样有两种存储方式,数组和链式存储,对于数组来说,我们利用二叉树的性质然后利用下标可以方便的找到一个节点的子节点和父节点. 二叉树的性质: 1.二叉树的第i层上至多有2i-1个节点 2.深度为K的二叉树至多有2k-1个节点 3.任何一个二叉树中度数为2的节点的个数必度数为0的节点数目少1. 说明:度数为0,为叶子节点. 4.具有n个节点的完全二叉树的深度为|_Log2N_|+1 5.若完全二叉树中的某节点编号为i,则若有左孩子编号为2i

二叉树的链式存储结构--二叉链表

1 二叉树的链式存储结构 //二叉链表的结点结构定义 typedef struct BiTNode { int data; struct BiTNode *lchild; struct BiTNode *rchild; }BiTNode; typedef struct BiTNode *BiTree; 结构示意图如下: 2 二叉树的遍历方法 (1)前序遍历:先访问根结,然后前序遍历左子树,再前序遍历右子树. (2)

二叉树的链式存储结构----二叉链表

头文件:head.h #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof()

java实现二叉树的链式存储

package com.fxr.二叉树链式存储; import java.util.Scanner; public class Tree { static final int MAXLEN = 20; static Scanner input = new Scanner(System.in); CBTType InitTree() { CBTType node; if((node = new CBTType()) != null) { System.out.println("请输入一个根节点的数

数据结构之自建算法库——二叉树的链式存储及基本运算

本文是数据结构基础系列(6):树和二叉树中第9课时二叉树的基本运算及其实现的例程. 单链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:btree.h,包含定义顺序表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef BTREE_H_INCLUDED #define BTREE_H_INCLUDED #define MaxSize 100 typedef char ElemType; typedef struct node { ElemType data; //

二叉树的链式存储

#include <stdio.h> #include <stdlib.h> #include <malloc.h> #define MAXSIZE 100 typedef char ElemType; typedef struct Node { ElemType data; struct Node *lchild; struct Node *rchild; }*BitTree,BitNode; /*二叉树的基本操作*/ void InitBitTree(BitTree

二叉树的链式结构

#include "string.h" #include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 100 /* 存

二叉树的链式存储结构

只复习一下二叉树的遍历,其他的以后再看 表示 /* bt_data_t for bi tree */ typedef char bt_data_t; #define NULL_DATA '\0' /* data_t for queue which will hold the pointer of bitree_t */ typedef void *data_t; typedef struct tree_node_t { bt_data_t data; struct tree_node_t *lc

10 二叉树-链式存储-递归遍历

终于进入非线性数据结构的第一站了! 先从简单的开始回忆起来吧! 1.二叉树的链式存储 用一个链表来存储一颗二叉树,每一个结点用链表的一个链结点来存储. 通常地,一个二叉链表至少包含3个域:数据域data.左指针域lchild.右指针域rchild. 现实应用的过程中,可以按照自己的需求添加其他指针域. 1 typedef struct BitNode{ 2 int data; 3 struct BitNode *lchild,*rchild; 4 }BitNode,*BiTree; 2.遍历 二