数据结构探险——树篇

以下内容源于慕课网的学习整理,如有侵权,请告知删除。


树存在概念中,是对数组或者链表的一种操作方式的概念。


一、与树有关的一些基础概念

(1)树

  • 有限节点的集合;

(2)度

  • 某个节点的直接孩子数目;

(3)叶节点

  • 终端节点

(4)祖先

  • 所有在它之上的节点

(5)深度

  • 节点的深度(节点所处的位置)
  • 树的深度(整棵树的深度)

(6)二叉树

  • 所有节点的度都小于等于2

(7)二叉树的遍历

  • 前中后,是针对“根”来说的。

(8)作用实例

  • 人机对战


二、二叉树的数组实现

1、换算公式

  • 父节点下标*2+1,得到,父节点的左孩子节点的下标;
  • 父节点下标*2+2,得到,父节点的右孩子节点的下标

2、示意图

  • 括号里面表示的是索引,或者说节点序号,外面的是数据。
  • 慕课网中只是按照这个图,来进行查找(遍历查找)、插入(已经确定在哪个位置上出入了)、删除(删除后赋值为0)等操作。


三、二叉树的链表实现

1、节点要素

  • 数据,左孩子指针,右孩子指针,父指针,索引(这里用来表征节点的序号)

2、删除元素

  • 要求把对应的子节点也删除掉;
  • 也可能要求只删除该点,然后该点的孩子节点指向该点的父节点;

3、前序遍历(根左右)



4、中序遍历(左根右)

首先是左526,然后是根0,接着是右897;

然后对526进行同样的操作,即左是2,根是5,右是6,则排序结果是256;

同理对897进行同样的操作,即左是9,根是8,右是7,则排序结果是987;

最后合成为256 0 987。


5、后序遍历(左右根)

首先是左526,然后是右897,接着是根0;

然后对526进行同样的操作,即左是2,右是6,根是5,则排序结果是265;

同理对897进行同样的操作,即左是9,右是7,根是8,则排序结果是978;

最后合成为265  978 0。



6、编码实现

  • 树类、节点类;
  • 节点类包含五要素:数据,左孩子指针,右孩子指针,父指针,索引(这里用来表征节点的序号)
  • 前序遍历(中序遍历、后序遍历就调换相应的位置即可)。
  • 对树的遍历操作,落实在根节点调用遍历函数。

node.h

#ifndef  NODE_H
#define NODE_H
class Node{
public :
	Node();
	int index;
	int data;
	Node *pLNOde;
	Node *pRNode;
	Node *pParent;
	Node *SerchNode(int index);
	void deleteNode();
	void Preorder();
	void Midorder();
	void Postorder();
};
#endif

node.cpp

#include "Node.h"
#include <iostream>
using namespace std;

Node::Node()
{
	index=0;
	data=0;
	pLNOde=NULL;
	pRNode=NULL;
	pParent=NULL;
};

Node* Node::SerchNode(int index)
{
	Node *temp=NULL;
	if (this->index==index)
		return this;
	if (this->pLNOde!=NULL)
	{	
		temp=this->pLNOde->SerchNode(index);
		if (temp!=NULL)
		{
			return temp;
		}
	}
    if (this->pRNode!=NULL)
	{
	    temp=this->pRNode->SerchNode(index);
		if (temp!=NULL)
		{
			return temp;
		}
    
	}
	return NULL;
};

void Node::deleteNode()
{
	if(this->pLNOde!=NULL) 
	{
		this->pLNOde->deleteNode();
	}
	if (this->pRNode!=NULL)
	{
		this->pRNode->deleteNode();
	}
	if (this->pParent!=NULL)
	{
		if (this->pParent->pLNOde==this)
		{
			this->pParent->pLNOde=NULL;
		}
		if (this->pParent->pRNode==this)
		{
			this->pParent->pRNode=NULL;
		}
	}
	delete this;
};

void Node::Preorder()
{
	cout<<this->data<<" "<<this->index<<endl;
	if (this->pLNOde!=NULL)
	{
		this->pLNOde->Preorder();
	}
	if (this->pRNode!=NULL)
	{
		this->pRNode->Preorder();
	}
};

void Node::Midorder()
{
	
	if (this->pLNOde!=NULL)
	{
		this->pLNOde->Midorder();
	}
	cout<<this->data<<" "<<this->index<<endl;
	if (this->pRNode!=NULL)
	{
		this->pRNode->Midorder();
	}
};

void Node::Postorder()
{
	if (this->pLNOde!=NULL)
	{
		this->pLNOde->Postorder();
	}
	
	if (this->pRNode!=NULL)
	{
		this->pRNode->Postorder();
	}
	cout<<this->data<<" "<<this->index<<endl;
};


tree.h

#ifndef  Tree_H
#define Tree_H
#include "Node.h"

class Tree
{
public:
	Tree();
	~Tree();
	Node *SerchNode(int index);//查找索引为index的那个节点,并返回指向该节点的指针
	bool addNode(int index,int direction,Node *node);//添加,在索引为index的节点上,添加一个节点node
	                                                 //左右方向由direction决定
	bool deleteNode(int index,Node *node);//删除
	void Preorder();//前序
	void Midorder();//中序
	void Postorder();//后序
private:
	Node *p_node;

};

#endif


tree.cpp

#include "Tree.h"
#include "Node.h"
#include <iostream>
using namespace std;


Tree::Tree()
{
	p_node=new Node();
};

Tree::~Tree()
{
	deleteNode(0,NULL);//这里调用的是tree中的删除节点函数,从根节点(0)开始
};

Node *Tree::SerchNode(int index)
{
		
   return p_node->SerchNode(index);
   
};

bool Tree::deleteNode(int index,Node *node)
{
	Node *temp=SerchNode(index);
	if (temp!=NULL)
	{
		if (node!=NULL)//传入的Node可以为null。是null时,表明不需要把要删除的节点的数据保存。
		{
			node->index=temp->index;
			node->data=temp->data;
		}
		
		temp->deleteNode();
		return true;
	}
	else
		return false;
};

bool Tree::addNode(int index,int direction,Node *node)
{
	Node *temp=SerchNode(index);
	if (temp)
	{
		Node *NewNode=new Node();
		if (NewNode==NULL)
		{
			return false;
		}
		
		NewNode->data=node->data;
		NewNode->index=node->index;
		
		if (direction==0)
		{
			temp->pLNOde=NewNode;
			NewNode->pParent=temp;
		}
		
		if (direction==1)
		{
			NewNode->pParent=temp;
			temp->pRNode=NewNode;
			
		}

		return true;
	}
	return false;
};

void Tree::Preorder()
{
	p_node->Preorder();
}

void Tree::Midorder()
{
	p_node->Midorder();
}

void Tree::Postorder()
{
	p_node->Postorder();
}

test.cpp

#include "Node.h"
#include "Tree.h"
#include <iostream>

using namespace std;
/*
           0(0)
	  1(1)      2(2)
  5(3)  7(4)  6(5)   9(6)
  
 */
int main()
{
	Tree *p=new Tree;//这里的p是指向根节点的指针
	
	Node *n2=new Node;
	n2->data=1;
	n2->index=1;
	
	Node *n3=new Node;
	n3->data=2;
	n3->index=2;
	
	Node *n4=new Node;
	n4->data=3;
	n4->index=3;
	
	Node *n5=new Node;
	n5->data=4;
	n5->index=4;
	
	Node *n6=new Node;
	n6->data=5;
	n6->index=5;
	
	Node *n7=new Node;
	n7->data=6;
	n7->index=6;
	
	Node *n8=new Node;
	n8->data=8;
	n8->index=8;
	
	Node *n9=new Node;
	n9->data=9;
	n9->index=9;	
	
	Node *n10=new Node;
	n10->data=10;
	n10->index=10;
	
	Node *n11=new Node;
	n11->data=11;
	n11->index=11;
	
	p->addNode(0,0,n2);
	p->addNode(0,1,n3);
	p->addNode(1,0,n4);
	p->addNode(1,1,n5);
	p->addNode(2,0,n6);
	p->addNode(2,1,n7);
//	p->addNode(4,0,n8);
//	p->addNode(4,1,n9);
//	p->addNode(6,0,n10);
//	p->addNode(6,1,n11);
	
	Node *n18=new Node;
	n18=p->SerchNode(10);
	if (n18!=NULL)
	{
		cout<<"index:"<<n18->index<<endl;
	}
	
	//Node *n12=new Node;
	//p->deleteNode(6,n12);
	p->Preorder();
	cout<<"========================="<<endl;
	p->Postorder();
	cout<<"========================="<<endl;
	p->Midorder();
	delete p;
	p=NULL;
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值