二叉树初步解析

二叉树

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

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

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

什么是树呢?????

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

这就是个树   
 
树是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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值