二叉树
这两天说的数据结构都是一些简单 的结构,为什么说之前的数据结构都是简单的呢????
这是因为这些数据结构都是顺序结构 ,,,其中都没有使用到递归这种难度细数大的结构 。。。。。
之前说的广义表,,,,,,倒是使用到了递归,但是这只是最基本的结构,,,还不算太难。。。。
今天我们在这说的是 树这种数据结构,,,,,
什么是树呢?????
下面来看一幅图 !!!!!!!!!!
这就是个树
树是n(n>=0)个有限个数据的元素集合,形状像一颗倒过来的树。
关于树 中 为我们有这么一些概念 要知道
节点:结点包含数据和指向其它节点的指针。
根节点:树第一个结点称为根节点。
结点的度:结点拥有的子节点个数。
叶节点:没有子节点的节点(度为0)。
父子节点:一个节点father指向另一个节点child,则child为孩子节点,father为父亲节点 。
兄弟节点:具有相同父节点的节点互为兄弟节点。
节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
根节点:树第一个结点称为根节点。
结点的度:结点拥有的子节点个数。
叶节点:没有子节点的节点(度为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;
}