数据结构学习笔记(五)二叉树及其C++实现
2016-07-18 20:17
357 查看
一、树的基本概念
树是一种层次结构,表达一对多的关系
树的节点:包含数据元素,还有指向其他节点的指针:孩纸指针,父节点指针
叶子节点,根节点,孩纸节点,双亲节点,兄弟节点,堂兄弟节点,祖先节点,子孙节点
节点的度:节点分支的个数
树的度:所有节点的度的最大值
树的路径:根节点到该节点上的所有节点连接起来的
层次:从根节点开始定义,根为第一层,根的孩纸为第二层,若节点中在第k层,其子树的根在第k+1层
树的深度(高度):树种节点的最大层次
有序树:树中节点的各个子树从左到右看做是有次序的
森林:即m个互不相交的树的集合
树的基本操作:求根节点,求双亲节点,求孩纸节点,建立一棵树,销毁一棵树等
二、二叉树
二叉树是每一个节点最多有两个子树的特殊的树,即树的度为2。二叉树是有序树,有左右子树之分。二叉树比较特殊的有完全二叉树、满二叉树,二叉平衡树等等。如下图所示:
二叉树的操作:新建树,销毁树,前序遍历,中序遍历,后续遍历,层次遍历,查找节点,树的高度,节点个数。。。。。。。。。
二叉树的性质:
二叉树在实现过程中,使用链表结构比较方便,下面给出二叉树的C++实现:
三、二叉树的C++实现
测试代码:
树是一种层次结构,表达一对多的关系
树的节点:包含数据元素,还有指向其他节点的指针:孩纸指针,父节点指针
叶子节点,根节点,孩纸节点,双亲节点,兄弟节点,堂兄弟节点,祖先节点,子孙节点
节点的度:节点分支的个数
树的度:所有节点的度的最大值
树的路径:根节点到该节点上的所有节点连接起来的
层次:从根节点开始定义,根为第一层,根的孩纸为第二层,若节点中在第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(); }
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)