二叉树初步解析

来源:互联网 发布:开心的网络用语怎么说 编辑:程序博客网 时间:2024/05/29 19:32

二叉树

这两天说的数据结构都是一些简单 的结构,为什么说之前的数据结构都是简单的呢????
这是因为这些数据结构都是顺序结构 ,,,其中都没有使用到递归这种难度细数大的结构 。。。。。

之前说的广义表,,,,,,倒是使用到了递归,但是这只是最基本的结构,,,还不算太难。。。。

今天我们在这说的是 树这种数据结构,,,,,

什么是树呢?????

下面来看一幅图  !!!!!!!!!!

这就是个树   
 
树是n(n>=0)个有限个数据的元素集合,形状像一颗倒过来的树。

关于树 中 为我们有这么一些概念 要知道 

节点:结点包含数据和指向其它节点的指针。
根节点:树第一个结点称为根节点。
结点的度:结点拥有的子节点个数。
叶节点:没有子节点的节点(度为0)。
父子节点:一个节点father指向另一个节点child,则child为孩子节点,father为父亲节点 。
兄弟节点:具有相同父节点的节点互为兄弟节点。
节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。


这就是一颗树 中 该有   的元素  。。。。。。

关于这类树  我们设置节点时》》》》》》
需要设置的节点结构  为 
节点   值   ;;;;
节点   的  子孩子。。。。。
 
因为这类树中的节点的子孩子的个数不确定   (可含有 0 ,一个  或者多个 )
我们可以Vector  容器来存储  节点的地址;;;;

在这里我们 可以  提供一种   普通树   节点的定义方法  
template<class T>struct  TreeNode {T  _value;TreeNode<T> * _leftchild;//左孩子TreeNode<T> * _rightbrother;//右兄弟};

这类节点的定义方法为  ::::左孩子右兄弟节点。。。。。。
图形表示为:::


这棵树中 我们使用 _leftchild  来保存一个节点的孩子节点。。。。_rightbrother 保存一个节点的兄弟节点

通过这样来保存一棵树。。。。。。



这种树状结构在计算机领域中是十分常见的。。。。》》》就比如说

计算机的文件系统目录
   这种就是使用这类树状结构来构造出来的。。。。



上面我们对于树的知识做了 一个好的开头,,,,,下面我们来看看今天的主要内容  二叉树 

二叉树


何为二叉树?????


二叉树 就是 一个特殊的树》》》》》
只是每一个节点的孩子个数不能超过两个。。。。。

针对于这类二叉树。。。。我们有提出了两种别的概念  。。。。
那就是  完全二叉树   和   满二叉树


完全二叉树、、、满二叉树 

完全二叉树、、、

一个树的前N-1层,,,都是满的(就是每个节点都含有两孩子节点),第N层节点从左到右分布 。。。。

满二叉树、、、

一棵树的N、、、、都是满的(每个节点都含有俩个节点)

也 就是说,,,,,满二叉树 一定是 完全二叉树  ,,,但是一个完全二叉树不一定是满二叉树。。。。


二叉树的结构

1、静态结构 



我们会对  每一个节点 按层 进行标号

如下图所示 、、、、、


对于完全二叉树而言 、、、、、在这里我们的标号  有一个规律》》》》》
假设当前节点的下标为m

那么该  节点的左孩子的下标    为    m*2+1;
该节点的右孩子的下标为      m*2+2;
该节点的父节点的下标为     (m-1)/2;

对于静态的存储   我们可以使用广度优先遍历 (按层来遍历)的方式 来进行访问。。。。。

我们可以利用队列  先进先出的特点来 解决这个问题》》》》

如果一个节点的有子节点 ,,,那么将他的左右孩子 放到队列里,,,,读取该节点的值 ,,,再将他从队列中PoP出来,,,,这样 一直向后走,,,,,知道队列为空 。。。。

2、链式结构

所谓链式结构就是像链表一样 ,,,,进行存储。。。。

在这里主要有两种结构
1、二叉链  (节点包含两个指针:左孩子、右孩子)
2、三叉链(节点包含 三个指针 :左孩子,右孩子,父节点)

因为三叉链管理起来相对麻烦,,,所以我们一般使用二叉链



对一颗二叉树我们要实现的基本操作  都有:

构造函数、
拷贝构造、
赋值操作符重载、
析构函数、
求节点的个数、
求树的深度、
求叶子节点的个数、
求第K层节点的个数、、、


在这里的这些函数都要用到递归、、、、、才能更好的实现

#pragma once#include<iostream>#include<assert.h>using namespace std;#include<queue>template<class T>struct BinaryTreeNode{T _data;//存储数据BinaryTreeNode<T> * _left;//左节点BinaryTreeNode<T> * _right;//右节点BinaryTreeNode(const T& data):_data(data),_left(NULL),_right(NULL){}};//二r叉树结构template<class T>class BinaryTree{typedef BinaryTreeNode<T> Node;public:BinaryTree(T * arr,size_t size, const T & invalid = T()){assert(arr);size_t index=0 ;_root = _CreateTree(arr,size,invalid,index);}BinaryTree(const BinaryTree<T>& b){_root = _Copy(b._root);}BinaryTree<T> & operator=(const BinaryTree<T>& b){if(this != &b ){BinaryTree<T> tem(b);std::swap(tem._root ,_root);}return *this;}~BinaryTree(){Destroy();}void Destroy(){_Destroy(_root);}public:Node * _Copy(Node * root){if(root == NULL)return  NULL;Node *cur   = new Node(root->_data);cur->_left = _Copy(root->_left);cur->_right  = _Copy(root->_right);return cur;}void _Destroy(Node * root){if(root ==NULL)return  ;_Destroy(root->_left);_Destroy(root->_right);delete root;}//求节点个数size_t Size(){return _Size(_root);}//求深度size_t Depth(){return _Depth(_root);}//求叶子节点个数size_t GetLeafSize(){return _GetLeafSize(_root);}//求第K层节点的个数size_t GetKLevelSize(size_t K){//assert(K> 0 );//return  _GetKLevelSize(_root,K);assert(K>0);size_t count = 0;size_t idex =1;_GetKLevelSize(_root,K,count,idex);return count;}//前序遍历void PreOrder(){_PreOrder(_root);cout<<endl;}//中序遍历void MidOrder(){_MidOrder(_root);cout<<endl;}//后续遍历void PostOrder(){_PostOrder(_root);cout<<endl;}//层序遍历void LevelOrder(){if(!_root)return ;queue<Node *> q ;q.push(_root);while(!q.empty()){Node * cur = q.front();cout<<cur->_data<<" ";q.pop();if(cur->_left){q.push(cur->_left);}if(cur->_right){q.push(cur->_right);}}cout<<endl;}protected:Node * _CreateTree(T *arr, size_t size, const T & invalid,size_t & idex){Node * newNode= NULL;if(idex <size  &&arr[idex] != invalid ){newNode =  new Node(arr[idex]);newNode->_left  = _CreateTree(arr,size,invalid,++idex);newNode->_right = _CreateTree(arr,size,invalid,++idex);}return newNode;}size_t _GetLeafSize(Node * root){if(!root)return 0 ;if(!root->_left && ! root->_right)return 1;return _GetLeafSize(root->_left)+ _GetLeafSize(root->_right);}size_t _Size(Node * root){if(root ==NULL)return 0;return 1+_Size(root->_left)+_Size(root->_right);}size_t _Depth(Node * root){if(root == NULL)return 0 ;int left =  _Depth(root->_left);int right  = _Depth(root->_right);return left >right ? left+1:right+1;}size_t _GetKLevelSize(Node * root,size_t k){if(root == NULL )return 0;if(k == 1 )return  1;return  _GetKLevelSize(root->_left,k-1) + _GetKLevelSize(root->_right,k-1);}void _GetKLevelSize(Node *root,const size_t K,size_t & count,size_t idex){if(root ==NULL)return ;if(idex == K){count++;return ;}_GetKLevelSize(root->_left,K,count,idex+1) ;_GetKLevelSize(root->_right,K,count,idex+1);}void _PreOrder(Node * root){if(root == NULL)return;cout<<root->_data<<" ";_PreOrder(root->_left);_PreOrder(root->_right);}void _MidOrder(Node * root){if(root == NULL)return;_MidOrder(root->_left);cout<<root->_data<<" ";_MidOrder(root->_right);}void _PostOrder(Node * root){if(root == NULL)return;_PostOrder(root->_left);_PostOrder(root->_right);cout<<root->_data<<" ";}protected:Node* _root;};void TestBinaryTree(){int array1[10] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};int array2[15] = {1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8};BinaryTree<int> b1(array1,10,'#');b1.PreOrder();b1.MidOrder();b1.PostOrder();b1.LevelOrder();cout<<b1.Size()<<endl;cout<<b1.Depth()<<endl;cout<<b1.GetKLevelSize(1)<<endl;BinaryTree<int> b2(b1);b2.PreOrder();BinaryTree<int> b3(array2,15,'#');b2 = b3;b1.PreOrder();b2.PreOrder();b3.PreOrder();cout<<b3.GetKLevelSize(5)<<endl;}















 











 
0 0
原创粉丝点击