您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记(五)二叉树及其C++实现

2016-07-18 20:17 357 查看
一、树的基本概念

          树是一种层次结构,表达一对多的关系

          树的节点:包含数据元素,还有指向其他节点的指针:孩纸指针,父节点指针

叶子节点,根节点,孩纸节点,双亲节点,兄弟节点,堂兄弟节点,祖先节点,子孙节点

          节点的度:节点分支的个数

          树的度:所有节点的度的最大值

          树的路径:根节点到该节点上的所有节点连接起来的

          层次:从根节点开始定义,根为第一层,根的孩纸为第二层,若节点中在第k层,其子树的根在第k+1层

          树的深度(高度):树种节点的最大层次

          有序树:树中节点的各个子树从左到右看做是有次序的

          森林:即m个互不相交的树的集合



          树的基本操作:求根节点,求双亲节点,求孩纸节点,建立一棵树,销毁一棵树等

二、二叉树

           二叉树是每一个节点最多有两个子树的特殊的树,即树的度为2。二叉树是有序树,有左右子树之分。二叉树比较特殊的有完全二叉树、满二叉树,二叉平衡树等等。如下图所示:



            二叉树的操作:新建树,销毁树,前序遍历,中序遍历,后续遍历,层次遍历,查找节点,树的高度,节点个数。。。。。。。。。
            二叉树的性质:



                   二叉树在实现过程中,使用链表结构比较方便,下面给出二叉树的C++实现:
三、二叉树的C++实现

#pragma once
//#include"arrayQueue.h"//使用标准库的队列
#include<deque>
#include<iostream>

using namespace std;

//节点结构
template<class T>
struct TreeNode
{
T element;//元素
TreeNode<T>* leftchild;//左孩子
TreeNode<T>* rightchild;//右孩子

TreeNode()
{
leftchild = rightchild = NULL;
}
TreeNode(const T& theElement)
{
element = theElement; leftchild = rightchild = NULL;
}
TreeNode(const T& theElement, TreeNode<T>* left, TreeNode<T>* right)
{
element = theElement; leftchild = left; rightchild = right;
}
};
//二叉树
template<class T>
class binaryTree
{
public:
//构造函数,复制构造函数和析构函数
binaryTree(){ root = NULL; theSize = 0; }//构造一个空树
~binaryTree(){ erase(); }//析构,通过调用erase函数删除所有节点
binaryTree(const binaryTree<T> &thebinaryTree)//复制构造函数
{
theSize = thebinaryTree.theSize;
if (theSize==0)//如果树为空
{
root = NULL;
return;
}
//树不为空,挨个节点复制
deque<TreeNode<T>*> q, p;//队列q存放原来的树的节点,p存放新建的树的节点
TreeNode<T>* sourceNode = thebinaryTree.root;
root = new TreeNode<T>(sourceNode->element);
TreeNode<T>* targetNode = root;
q.push_back(sourceNode);
p.push_back(targetNode);
//将sourceNode复制到targetNode
while (q.empty()==0)
{
sourceNode = q.front();
targetNode = p.front();
if (sourceNode->leftchild != NULL)
{
q.push_back(sourceNode->leftchild);
targetNode->leftchild = new TreeNode<T>(sourceNode->leftchild->element);
p.push_back(targetNode->leftchild);
}
if (sourceNode->rightchild != NULL)
{
q.push_back(sourceNode->rightchild);
targetNode->rightchild = new TreeNode<T>(sourceNode->rightchild->element);
p.push_back(targetNode->rightchild);
}
q.pop_front();
p.pop_front();
}
}
//各种成员函数
int size() const{ return theSize; }//树的大小
bool empty() const{ return theSize == 0; }//树是否为空
T* rootelement() const//返回根节点的地址
{
if (theSize == 0){  return NULL; }
else { return &root->element; }//注意优先级
}
int height() const { return height(root); }//通过调用height(root)来求整个树的高度

void makeTree(const T& element, binaryTree<T>& left, binaryTree<T>& right);//建造一个树
binaryTree<T> removeLeftSubtree();//移除左子树
binaryTree<T> removeRightSubtree();//移除右子树

//整个树的前序遍历,形参表示一个函数用来处理遍历的当前节点,theVist是函数地址,返回值是void,其参数是TreeNode<T>*
void preOrder(void(*theVisit) (TreeNode<T>*))   { preOrder(theVisit, root); }
//整个树的中序遍历,
void inOrder(void (*theVisit) (TreeNode<T>*))	{ inOrder(theVisit,root);	}
//整个树的后序遍历,
void postOrder(void (*theVisit) (TreeNode<T>*))	{ postOrder(theVisit,root);	}
//整个树的层次遍历
void levelOrder(void(*theVisit) (TreeNode<T>*)) { levelOrder(theVisit, root); }

//几种不同的输出
void preOrderOutput() { preOrder(output,root); cout << endl; }
void inOrderOutput() { inOrder(output,root); cout << endl; }
void postOrderOutput() { postOrder(output,root); cout << endl; }
void levelOrderOutput() { levelOrder(output,root); cout << endl; }

//删除树,清空整个树
void erase()
{
postOrder(dispose,root);
root = NULL;
theSize = 0;
}
//查找树的某一个节点
bool find(const T& theElement)
{
deque<TreeNode<T>*> q;//队列
TreeNode<T> *t = root;
while (t != NULL)
{
if (t->element==theElement)
{
return true;
}

// 将t的孩纸加入队列
if (t->leftchild != NULL)
q.push_back(t->leftchild);
if (t->rightchild != NULL)
q.push_back(t->rightchild);

// 获得下一个节点
if (q.empty() == 0)
t = q.front();
else
break;
q.pop_front();
}
return false;
}

protected:
TreeNode<T>* root;//指向根节点的指针
int theSize;//树的元素个数

//前序遍历以t为根节点的树,参数visit是对节点的处理函数,
static void preOrder(void(*visit) (TreeNode<T>*), TreeNode<T> *t)
{
if (t != NULL)
{
visit(t);
preOrder(visit,t->leftchild);
preOrder(visit,t->rightchild);
}
}
//中序遍历以t为根节点的树,参数visit是对节点的处理函数,
static void inOrder(void(*visit) (TreeNode<T>*), TreeNode<T> *t)
{
if (t != NULL)
{
inOrder(visit,t->leftchild);
visit(t);
inOrder(visit,t->rightchild);
}
}
//后序遍历以t为根节点的树,参数visit是对节点的处理函数,
static void postOrder(void(*visit) (TreeNode<T>*), TreeNode<T> *t)
{
if (t != NULL)
{
postOrder(visit,t->leftchild);
postOrder(visit,t->rightchild);
visit(t);
}
}
//层次遍历以t为根节点的树
void levelOrder(void(*theVisit) (TreeNode<T>*),TreeNode<T>* t)
{
deque<TreeNode<T>*> q;//队列
//TreeNode<T> *t = root;
while (t != NULL)
{
theVisit(t);  // 处理节点t

// 将t的孩纸加入队列
if (t->leftchild != NULL)
q.push_back(t->leftchild);
if (t->rightchild != NULL)
q.push_back(t->rightchild);

// 获得下一个节点
if (q.empty() == 0)
t = q.front();
else
return;
q.pop_front();
}
}
//返回节点t为根节点的树的节点个数,使用层次遍历好写,其他遍历方法也可以实现。。
static int countNodes(TreeNode<T> *t)
{
int count = 0;
deque<TreeNode<T>*> q;//队列
while (t != NULL)
{
count++;  // 处理节点t

// 将t的孩纸加入队列
if (t->leftchild != NULL)
q.push_back(t->leftchild);
if (t->rightchild != NULL)
q.push_back(t->rightchild);

// 获得下一个节点
if (q.empty() == 0)
t = q.front();
else
break;
q.pop_front();

}
return count;
}
static void dispose(TreeNode<T> *t) { delete t; }//删除节点t
static void output(TreeNode<T> *t)	{ cout << t->element << ' ';	}//输出节点t
static int height(TreeNode<T> *t)//返回节点t为根节点的树的高度
{
if (t == NULL)
return 0;                    // 空树
int hl = height(t->leftchild);  // 左树高度
int hr = height(t->rightchild); // 右树高度
if (hl > hr)
return ++hl;
else
return ++hr;
}
};
//创建一棵树
template<class T>
void binaryTree<T>::makeTree(const T& element, binaryTree<T>& left, binaryTree<T>& right)
{
root = new TreeNode<T>(element, left.root, right.root);
theSize = left.theSize + right.theSize + 1;
left.root = right.root = NULL;
left.theSize = right.theSize = 0;

}

template<class T>
binaryTree<T> binaryTree<T>::removeLeftSubtree()
{// 删除左子树
if (theSize == 0)
{
cerr << "The tree is empty"; exit(0);
}
binaryTree<T> leftSubtree;
leftSubtree.root = root->leftchild;
leftSubtree.theSize = countNodes(leftSubtree.root);
//原来的树的左子树为空,theSize改变
root->leftchild = NULL;
theSize -= leftSubtree.theSize;

return leftSubtree;//需要定义复制构造函数
}

template<class T>
binaryTree<T> binaryTree<T>::removeRightSubtree()
{// 删除右子树

if (theSize == 0)
{
cerr << "The tree is
9f2a
empty"; exit(0);
}

binaryTree<T> rightSubtree;
rightSubtree.root = root->rightchild;
rightSubtree.theSize = countNodes(rightSubtree.root);

root->rightchild = NULL;
theSize -= rightSubtree.theSize;

return rightSubtree;
}


测试代码:

#include "binaryTree.h"
#include<iostream>
using namespace std;
void main()
{
binaryTree<int> a, x, y, z;
y.makeTree(1, a, a);
z.makeTree(2, a, a);
x.makeTree(3, y, z);
y.makeTree(4, x, a);
cout << "Number of nodes = ";
cout << y.size() << endl;
cout << "height = ";
cout << y.height() << endl;
cout << "Rootment of The tree is ";
cout << *(y.rootelement()) << endl;
cout << "Preorder sequence is ";
y.preOrderOutput();
cout << "Inorder sequence is ";
y.inOrderOutput();
cout << "Postorder sequence is ";
y.postOrderOutput();
cout << "Level order sequence is ";
y.levelOrderOutput();
(y.find(4) == 1) ? cout << "The tree have 4" : cout << "The tree have not 4";
cout << endl;
cout << "The leftSubtree:";
y.removeLeftSubtree().postOrderOutput();
cout << "The copy of the Tree is ";
binaryTree<int> s = y;
s.levelOrderOutput();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构