• 二叉树


    二叉树

    实现用线性结构表示非 线性结构

    数---》二叉树---》满二叉树---》完全二叉树

    一、二叉树的概念

    二叉树也是树的一种,其存储结构及其算法都较为简单,因此二叉树显得特别重要。

    二叉树:是每个节点的最多有两个子树的有序树--度最多为2的有序树

    注意:在有序树中,虽然一个节点的孩子之间是有左右次序的,但是若该节点只有一个孩子,就无须区分左右次序,而在二叉树中,即使是一个孩子也有左右之分

    一棵数变成二叉树:目的想去利用数组的方式保存(但是可能会存在浪费)

    二、二叉树的五种表现形式

    1.空树

    2.只有一个根节点的二叉树

    3.只有一个左子树的二叉树

    4.只有一个右子树的二叉树

    5.有左右子树的二叉树

    三、二叉树的特性

    1.二叉树的每个节点至多只有二棵子树(不存在度大于2的节点)

    2.二叉树的子树哟左右之分,次序不能颠倒

    3.二叉树的第n层至多有2^(n-1)个节点

    4.深度为k的二叉树至多有2^(k)-1个节点

    5.任意一棵二叉树中,如果度为2的节点数为n,度为0的节点数为m,m=n+1

    四、满二叉树

    1.二叉树中第n层上的节点数必须为2^(n-1)个节点

    2.二叉树如果高度为k,这个二叉树中的节点数必须为2^(k)-1个

    3.在满二叉树中不存在度为1的节点,每一个分支节点都有2棵高度一致的子树所有叶节点都在最下一层

    4.一棵二叉树如果变成了满二叉树,可以利用数组且,且没有空间浪费

    五、完全二叉树

    1.若一棵二叉树最多只有最下面的两层其节点的度可以小于2,并且最下一层上的节点都集中在该层最左边的若干位置上,则此二叉树称为完全二叉树

    2.满二叉树是完全二叉树,完全二叉树不一定是满二叉树

    完全二叉树的特性

    1.从一棵满二叉树的最下一层(叶节点那一层),从右往左依次删除若干(0-n)叶节点后形成的数叫完全二叉树

    2.在一棵完全二叉树中,如果一个节点没有左子树,这个节点必然没有右子树,这个节点是叶节点。但是可以有左子树,没有右子树

    完全二叉树中的下标规律

    1.根节点下标默认为0

    2.树中的任意一个节点它的下标为i,那么这个节点的父节点下标必然为(i-1)>>1

    3.树中的任意一个节点它的下标为i,那么这个节点的左子树下标必然是2*i+1,右子树的下标必然为2乘i+2

    4.除开根节点,左子树的下标为奇数,右子树的下标为偶数

    六、二叉树的遍历

    1、先序(根)

    先访问根节点,然后访问左孩子,最后访问右孩子

    2、中序(根)

    先访问左孩子,然后访问根节点,最后访问右孩子

    3、后序(根)

    先访问左孩子,再访问右孩子,最后访问根节点

    七、完全二叉树的代码示例

    类模板--binarytree.h

    #pragma once
    template<class T>
    class mytree
    {
    	T* pbuff;
    	int len;//动态数组当前元素个数
    	int maxsize;//动态数组最大容量
    public:
    	mytree();
    	~mytree();
    	void clear();//清除树
    public:
    	bool find(T const&findval)const;//判断是否在树中找到这个数据
    	void appendnode(T const&data);//申请内存扩容,并插入数据
    	void inittree(T arr[], int length);//初始化树
    	void printftree();//提供接口,打印树
    	T getparentval(int elemval)const;//找父节点
    	T getleftval(int elemval)const;//找左子树
    	T getrightval(int elemval)const;//找右子树
    	T getleftbrother(int elemval)const;//找左兄弟
    	T getrightbrother(int elemval)const;//找右兄弟
    private:
    	int _find(T const& findval)const;//查找数据,返回下标
    	void _printftree(int index);//打印树
    };
    
    template<class T>
    mytree<T>::mytree()//构造函数
    {
    	pbuff = nullptr;
    	len = maxsize = 0;
    }
    
    template<class T>
     mytree<T>::~mytree()
    {
    	 clear();
    }
    
    template<class T>
    void mytree<T>::clear()
    {
    	if (pbuff)
    		delete[]pbuff;
    	pbuff = nullptr;
    	len = maxsize = 0;
    }
    
    template<class T>
    bool mytree<T>::find(T const & findval) const
    {
    	return _find(findval) != -1;
    }
    
    template<class T>
    void mytree<T>::appendnode(T const & data)
    {
    	if (len >= maxsize)
    	{
    		maxsize = maxsize + ((maxsize >> 1) ? (maxsize >> 1) : 1);
    		T* ptemp = new T[maxsize];
    		memcpy(ptemp, pbuff, sizeof(T)*len);
    		if (pbuff)
    		{
    			delete[]pbuff;
    		}
    		pbuff = ptemp;
    	}
    	pbuff[len++] = data;
    }
    
    template<class T>
    void mytree<T>::inittree(T arr[], int length)//传一个数组进来
    {
    	clear();//先将树中的内容清除掉
    	if (length > 0)
    	{
    		maxsize = len = length;
    		pbuff = new T[maxsize];
    		for (int i = 0; i < maxsize; i++)
    		{
    			pbuff[i] = arr[i];//用这个数组来初始化动态数组
    		}
    	}
    }
    
    template<class T>
    void mytree<T>::printftree()
    {
    	_printftree(0);//从根节点开始打印
    }
    
    template<class T>
    T mytree<T>::getparentval(int elemval) const//打印传进来的数据的父节点
    {
    	int index = _find(elemval);
    	if (index < 0)
    		throw "发生错误";
    	return pbuff[(index - 1) >> 1];
    }
    
    template<class T>
    T mytree<T>::getleftval(int elemval) const//找这个数据的左子树
    {
    	int index = _find(elemval);
    	if (2 * index + 1 >= len || index < 0)
    	{
    		throw "out_range";
    	}
    	return pbuff[2 * index + 1];
    }
    
    template<class T>
    T mytree<T>::getrightval(int elemval) const
    {
    	int index = _find(elemval);
    	if (2 * index + 2 >= len && index < 0)
    	{
    		throw "发生错误";
    	}
    	return pbuff[2 * index + 2];
    }
    
    template<class T>
    T mytree<T>::getleftbrother(int elemval) const
    {
    	int index = _find(elemval);
    	if (index < 0)
    	{
    		throw "发生错误";
    	}
    	if (index % 2 != 0)
    	{
    		throw "this is left";
    	}
    	return pbuff[index - 1];
    }
    
    template<class T>
    T mytree<T>::getrightbrother(int elemval) const
    {
    	int index = _find(elemval);//先找到这个元素的下标
    	if (index < 0)
    	{
    		throw "发生错误";
    	}
    	if (index % 2 == 0)
    	{
    		throw "this is right";
    	}
    	return pbuff[index + 1];
    }
    
    template<class T>
    int mytree<T>::_find(T const & findval) const
    {
    	for (int i = 0; i < len; i++)
    	{
    		if (findval == pbuff[i])
    		{
    			return i;
    		}
    	}
    	return -1;
    }
    
    template<class T>
    void mytree<T>::_printftree(int index)
    {
    	if (index < len)
    	{
    		//先序的打印方法
    		printf("%d
    ", pbuff[index]);//打印根节点
    		_printftree(2 * index + 1);//打印左子树
    		_printftree(2 * index + 2);//打印右子树
    
    		//中序打印
    		//_printftree(2 * index + 1);//打印左子树
    		//printf("%d
    ", pbuff[index]);//打印根节点
    		//_printftree(2 * index + 2);//打印右子树
    
    		//后序打印
    	//	_printftree(2 * index + 1);//打印左子树
    	//	_printftree(2 * index + 2);//打印右子树
    	//	printf("%d
    ", pbuff[index]);//打印根节点
    	}
    }
    
    

    main.cpp

    #include<iostream>
    #include"binarytree.h"
    using namespace std;
    int main()
    {
    	mytree<int> ms;
    	int arr[10] = { 0,1,2,3,4,5,6,7,8,9};
    	ms.inittree(arr, 10);
    	for (int i = 0; i <5; i++)
    	{
    		ms.appendnode((i+1)*10);
    	}
    	ms.printftree();
    	return 0;
    }
    
  • 相关阅读:
    Openjudge-计算概论(A)-单词翻转
    Openjudge-计算概论(A)-字符串排序
    Openjudge-计算概论(A)-过滤多余的空格
    Openjudge-计算概论(A)-单词倒排
    Openjudge-计算概论(A)-统计字符数
    Openjudge-计算概论(A)-奇数单增序列
    碎碎的光阴(湖北荆门一考生)
    Openjudge-计算概论(A)-找和为K的两个元素
    php延迟加载的示例
    php排序测试
  • 原文地址:https://www.cnblogs.com/Kissfly123/p/14636068.html
Copyright © 2020-2023  润新知