走近二叉树

树的简介

一起探索二叉树

两种代码实现方式


树的简介

树是什么呢????
在我看来,树就是结点的有限集合,n个结点构成某种所谓的“家族关系”,就形成了树。
在这里插入图片描述
上述括号里面的数字均为结点的索引结点,括号外面的都为结点存储的数据。
树的一些相关概念:
1.孩子:就是子结点,可以说是某个结点的后代,比如说,上图中,1和2就是0的子结点。
2.双亲:比如说1就是8的父结点。
3。度:当前结点直接的孩子,比如说,0直接的子结点就是1和2,所以它的度为2.
4.叶子:终端结点,比如说,3,4,5,6结点均到底了,不能再下去了,到了终端,因此就是叶子。
5.根:非终端结点,上述,0,1,2都没到底,均为根。
6.深度:
结点深度:看它是第几代。
树的深度:看这个树有几代。

一起探索二叉树

二叉树是树的一种,就是每一个结点的度数都不大于2,最多有两个孩子。
二叉树有几种不同的遍历,都和根结点输出的顺序有关,其分别为
前序遍历:根结点->左结点->右结点
中序遍历:左结点->根结点->右结点
后序遍历:左结点->右结点->根结点
以下是我自己做的图形演示(稍微丑点了,别介意哈)
在这里插入图片描述
六、二叉树的性质:

1、若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2i-1个节点

2、若规定只有根节点的二叉树的深度为1,则深度为k的二叉树的最大节点数是2k-1

3、对任何一棵二叉树,如果其叶子节点个数为n0,度为2的非叶子节点个数为n2,则n0=n2+1

4、具有n个节点的完全二叉树的深度k为log2(n+1)向上取整

5、对于具有n个节点的完全二叉树,如果按照从上至下从左至右的顺序对所有结点从0开始编号,则对于序号为i的节点有:

(1)如果i>=0,则序号为i节点的双亲结点的序号为(i-1)/2;如果i=0,则序号i节点无双亲结点

(2)如果2i+1<n,则序号i结点的左孩子的序号为2i+1,右孩子的序号为2i+2;如果2i+1>=n,则序号i节点无孩子节点
原文链接:https://blog.csdn.net/zhuboke3344/article/details/78759501

两种代码实现方式

数组实现:
规定:
假设结点索引为index,那么它的左子结点的索引(下标)为:index2+1
右子结点为index
2+2
方法:
1.树的创建和销毁
2.树中结点的搜索
3.添加与删除
4.遍历

class Tree
{
	public:
		
	    Tree(int size,int *Root)         //构造函数 
        {
        	my_Tree = new int[size];
		    length=size;       //记录树的大小,多少个结点
			for(int i=0;i<size;i++)
			{
				my_Tree[i]=0;   //初始化 
			}
			my_Tree[0]=*Root;    //初始化一个根结点 
	    }
	    ~Tree()
		{
			delete[] my_Tree;
			my_Tree=NULL;
		}
		int Search(int index)        //搜索树 
		{
			if(index<0||index>=length||my_Tree==0)
			{
				return NULL;
			}
			return my_Tree[index];
		}
		bool addTree(int index,int direction,int *Node)          //给指定结点索引index添加子结点direction表示往左还是右插入结点Node  ,
		{
			if(index<0||index>=length||my_Tree[index]==0)
			{
				return false;
			}
			if(direction==0)               //往左边插入 
			{
				if(my_Tree[index*2+1]!=0)
				{
					return false;
				}
				my_Tree[index*2+1]=*Node;
				
			}
			if(direction==1)             //往右插入子结点
			{
				if(my_Tree[index*2+2]!=0)
				{
					return false;
				}
				my_Tree[index*2+2]=*Node;
			}
		}
		bool popTree(int index,int *Node)
		{
			if(index<0||index>=length||my_Tree[index]==0)
			{
				return false;
			}
			*Node=my_Tree[index];
			my_Tree[index]=0;               //结点位置置为空 
			return true;
		}
		void Traverse()
		{
			for(int i=0;i<length;i++)
			{
				cout<<my_Tree[i]<<" ";
			}
			cout<<endl;
		}
	private:
		int *my_Tree;         //指针数组 
	    int length;              //结点长度
}; 

链表实现:
规定:
假设结点索引为index,那么它的左子结点的索引(下标)为:index2+1
右子结点为index
2+2
方法:
创建树,销毁树,搜索结点,添加删除结点,前序遍历,中序遍历,后序遍历。
结点要素:索引(找到结点),数据(存储数据),左孩子指针(创建左子树),右孩子指针(创建右子树),父结点指针(删除结点的时候,要找到父结点,然后让父结点指向空)。

扫描二维码关注公众号,回复: 10046549 查看本文章
class Node                  //结点类 
{
	public:
		int data;           //数据 
		int index;          //索引 
		Node *left;         //左孩子指针 
		Node *right;        //右孩子指针 
		Node *parent;       //父结点指针 
		Node()              //结点构造函数,初始化所有属性 
		{
			index=0;
			data=0;
			left=NULL;
			right=NULL;
			parent=NULL;
		}
		void deleteNode()        //先找到父节点,看是它的左孩子还是右孩子,然后再把父亲相应的指针指为空,然后再自杀 ,然后把它的子代结点全部销毁
		{
			if(this->left!=NULL)
			{
				this->left->deleteNode();    //用递归销毁左子树
			}
			if(this->right!=NULL)
			{
				this->right->deleteNode();   //用递归销毁右子树
			}
			if(this->parent!=NULL)            //让父结点的指向变为空
			{
				if(this->parent->left==this)
				{
					this->parent->left=NULL;
				}
				if(this->parent->right==this)
				{
					this->parent->right=NULL;
				}
			}
			delete this;                            //销毁自己
			 
		}
		Node *SearchNode(int index)      //查找搜索结点,使用递归
		{
			if(this->index==index)
			{
				return this;
			}
			Node *temp = NULL;
			if(this->left!=NULL)
			{
				if(this->left->index==index)
				{
					return this->left;
				}
				else
				{
					temp=this->left->SearchNode(index);
					if(temp!=NULL)
					{
						return temp;
					}
				}
				
			}
			if(this->right!=NULL)
			{
				if(this->right->index==index)
				{
					return this->right;
				}
				else
				{
					temp=this->right->SearchNode(index);
					if(temp!=NULL)
					{
						return temp;
					}
				}
			}
			
			return NULL;
		}
		void preTraverse()                          //前序遍历:根结点->左结点->右结点
		{
			cout<<this->data<<" "<<this->index<<endl;        //输出根结点的数据和索引
			if(this->left!=NULL)
			{
				this->left->preTraverse();                              //左子树结点
			}
			if(this->right!=NULL)
			{
				this->right->preTraverse();                           //右子树结点
			}
		}  
		void inTraverse()                                                //中序遍历:左子树->根结点->右子树,就是把根结点输出顺序改变了一下
		{
		
			if(this->left!=NULL)
			{
				this->left->inTraverse();
			}
			cout<<this->data<<" "<<this->index<<endl;
			if(this->right!=NULL)
			{
				this->right->inTraverse();
			}
		}
		void lastTraverse()                                  //后序遍历:左子树->右子树->根结点
		{
				if(this->left!=NULL)
			{
				this->left->lastTraverse();
			}
			
			if(this->right!=NULL)
			{
				this->right->lastTraverse();
			}
			cout<<this->data<<" "<<this->index<<endl;
		}
};
class Tree                                                  //二叉树类
{
	public:
		Tree()                                                //构造函数
		{
			root = new Node();
		}
		Node *Search(int index)      //搜索结点 
		{
			return root->SearchNode(index);
		}
		bool addNode(int index,int direction,Node *node)    //往指定的结点左右添加子结点
		{
			Node *temp = Search(index);
			if(temp==NULL)
			{
				return false;
			}
			else
			{
				Node *pnode = new Node();                     //把需要添加的结点赋给pnode
				pnode->data=node->data;
				pnode->index=node->index;
				pnode->parent=temp;                              //找到父结点
				if(direction==0)
				{
					temp->left=pnode;
				}
				if(direction==1)
				{
					temp->right=pnode; 
				}
				
			
			}
			return true;
		}
		bool deleteNode(int index,Node *node)             //销毁结点以及其子代
		{
			Node *temp = Search(index);
			if(temp==NULL)
			{
				return false;
			}
			if(node!=NULL)
			node->data=temp->data;
			temp->deleteNode();
			return true;
		}
		~Tree()                                       //析构函数
		{
			deleteNode(0,NULL);        //从根结点开始删除 
			//root->deleteNode();
		}
		void preTraverse()                //前序遍历
		{
			root->preTraverse();
		} 
		void inTraverse()                 //中序遍历
		{
			root->inTraverse();
		}
		void lastTraverse()               //后序遍历
		{
			root->lastTraverse();
		}
		
	private:
		Node *root;                      //根结点
};

以上便是我对树的一点点浅薄的看法,后续还会更新哦。

发布了22 篇原创文章 · 获赞 27 · 访问量 2851

猜你喜欢

转载自blog.csdn.net/weixin_44346470/article/details/100163641