前言
学习了栈和队列后,我们接着在数据结构的海洋中遨游。这时的我已经被各种栈和队列折腾的快不行了,然而,当学习了树之后,才发现自己还是太年轻,跟树比起来,栈和队列是那么的和谐与友好。先来小试牛刀一把,看看最简单的二叉树是怎么实现的:
二叉树的实现
二叉树是节点的有限集合,他或者为空,或者有一个根节点及两颗互不相交的左右子树构成,而左右子树有都是二叉树。写到这里,是不是已经体会到了一点二叉树与递归的暧昧关系。
若一棵树的任意一层节点数都达到了最大值,则这棵二叉树称为满二叉树。
而如果将满二叉树自右向左依次删掉几个节点(注意不要跳过节点),那样的树就是完全二叉树。
二叉树的常用性质
1. 一棵非空二叉树的第i层上最多有个节点(i>=1)。
2. 一棵高度为k的二叉树,最多有 - 1个节点。
3. 对于一棵非空二叉树,如果叶子节点数为a,度为2的节点数为吧b,则a = b + 1。
4. 具有n个节点的完全二叉树的高度为k = [log2(n)] + 1。(其中[ ]指不比里面数大的最大整数)
说了这么多,下面就来看看具体的C++实现:
#include <iostream>
using namespace std;
//父类
template<class elemType>
class queue {
public:
virtual bool isEmpty() = 0;
virtual void enQueue(const elemType &x) = 0;
virtual elemType deQueue() = 0;
virtual elemType getHead() = 0;
virtual ~queue(){};
};
template<class elemType>
class linkQueue: public queue<elemType>
{
private:
struct node{
elemType data;
node *next;
node(const elemType &x, node *N = NULL){
data = x;
next = N;
}
node():next(NULL){}
~node(){}
};
node *front , *rear;
public:
linkQueue(){
front = rear = NULL;
}
~linkQueue(){
node *tmp;
while(front != NULL){
tmp = front;
front = front -> next;
delete tmp;
}
}
bool isEmpty(){
return front == NULL;
}
void enQueue(const elemType &x){
if(rear == NULL){
front = rear = new node(x);
}
else{
rear -> next = new node(x);
rear = rear -> next;
}
}
elemType deQueue(){
node *tmp = front;
elemType value = front -> data;
front = front -> next;
if(front == NULL){
rear = NULL;
}
delete tmp;
return value;
}
elemType getHead()
{
return front-> data;
}
};
//子类
template<class T>
class bTree{
public:
virtual void clear() = 0;
virtual bool isEmpty()const = 0;
virtual T Root(T flag)const = 0;
virtual T parent(T x, T flag)const =0;
virtual T lchild(T x, T flag)const = 0;
virtual T rchild(T x, T flag)const = 0;
virtual void delLeft(T x) = 0;
virtual void delRight(T x) = 0;
virtual void preOrder() const = 0;
virtual void midOrder() const = 0;
virtual void postOrder() const = 0;
virtual void levelOrder() const = 0;
};
template<class T>
class binaryTree:public bTree<T>{
friend void printTree(const binaryTree &t, T flag);
private:
struct Node{
Node *left, *right, *parent;
T data;
Node():left(NULL), right(NULL), parent(NULL){}
Node(T item, Node *L = NULL, Node *R = NULL):data(item), left(L), right(R){}
~Node(){};
};
Node *root;
public:
binaryTree():root(NULL){}
binaryTree(T x){
root = new Node(x);
}
~binaryTree(){
clear(root);
}
void clear(Node *t){
if(t == NULL){
return;
}
clear(t -> left);
clear(t -> right);
delete t;
t = NULL;
}
void clear(){
clear(root);
}
bool isEmpty()const{
return root == NULL;
}
T Root(T flag)const{
if(root == NULL){
return flag;
}
else{
return root->data;
}
}
Node *find(T x, Node *t)const{
Node *tmp;
if(t == NULL){
return t;
}
if(t -> data == x){
return t;
}
if(tmp = find(x, t -> left)){
return tmp;
}
else{
return (find(x, t -> right));
}
}
T lparent(T x, T flag)const{
}
T lchild(T x, T flag)const{
Node *tmp = find(x, root);
if(tmp == NULL || tmp -> left == NULL){
return flag;
}
return tmp -> left -> data;
}
T rchild(T x, T flag)const{
Node *tmp = find(x, root);
if(tmp == NULL || tmp -> right == NULL){
return flag;
}
return tmp -> right -> data;
}
void delLeft(T x){
Node *tmp = find(x, root);
if(tmp == NULL){
return;
}
clear(tmp -> left);
}
void delRight(T x){
Node *tmp = find(x, root);
if(tmp == NULL){
return;
}
clear(tmp -> right);
}
//preorder traverse
void preOrder(Node *t)const{
if(t == NULL){
return;
}
cout << t -> data << ' ';
preOrder(t -> left);
preOrder(t -> right);
}
void preOrder()const{
preOrder(root);
}
//midorder traverse
void midOrder(Node *t)const{
if(t == NULL){
return;
}
midOrder(t -> left);
cout << t -> data << ' ';
midOrder(t -> right);
}
void midOrder()const{
midOrder(root);
}
//postorder traverse
void postOrder(Node *t) const{
if(t == NULL){
return;
}
postOrder(t -> left);
postOrder(t -> right);
cout << t -> data << ' ';
}
void postOrder()const{
postOrder(root);
}
//levelorder traverse
void levelOrder()const{
linkQueue<Node *>que;
Node *tmp;
que.enQueue(root);
while(!que.isEmpty()){
tmp = que.deQueue();
cout << tmp -> data << ' ';
if(tmp -> left){
que.enQueue(tmp -> left);
}
if(tmp -> right){
que.enQueue(tmp -> right);
}
}
}
//creat a binary tree
void creatTree(T flag){
linkQueue<Node *>que;
Node *tmp;
T x, ldata, rdata;
cout << "Please input the root:";
cin >> x;
root = new Node(x);
que.enQueue(root);
while(!que.isEmpty()){
tmp = que.deQueue();
cout << "Input the left node and right node:";
cin >> ldata >> rdata;
if(!ldata != flag){
que.enQueue(tmp -> left == new Node(ldata));
}
if(!rdata != flag){
que.enQueue(tmp -> left == new Node(rdata));
}
}
}
T parent(T x, T flag)const{
return flag;
}
//Judge if it is a complete binary tree
void isCBT(){
linkQueue<Node *> que;
int lastId = 1, nodeCount = 1;
root -> data = 1;
Node *tmpNode, *son;
if(root == NULL){
cout << 'Y';
return;
}
que.enQueue(root);
while(!que.isEmpty()){
tmpNode = que.deQueue();
if(tmpNode -> left != NULL){
nodeCount = nodeCount + 1;
son = tmpNode -> left;
son -> data = (tmpNode -> data) * 2;
lastId = son -> data;
que.enQueue(son);
}
if(tmpNode -> right != NULL){
nodeCount = nodeCount + 1;
son = tmpNode -> right;
son -> data = (tmpNode -> data) * 2 + 1;
lastId = son -> data;
que.enQueue(son);
}
}
if(nodeCount == lastId){
cout << 'Y';
}
else{
cout << 'N';
}
}
};
总结
本节内容主要是介绍了树的基本概念以及二叉树的定义、特性和实现代码,包括构建树,四种遍历树的操作,以及判断数是否为完全二叉树的方法,如果你已经觉得树如此复杂,那只能说“小朋友,这才是冰山一角中的一角”,想看看冰山的真面目,就鼓足干劲接着学习吧。