编程语言
首页 > 编程语言> > C++ 不知树系列之初识树(树的邻接矩阵、双亲孩子表示法……)

C++ 不知树系列之初识树(树的邻接矩阵、双亲孩子表示法……)

作者:互联网

1. 前言

树是一种很重要的数据结构,最初对数据结构的定义就是指对的研究,后来才广义化了数据结构这个概念。从而可看出在数结构这一研究领域的重要性。

重要的原因是,它让计算机能建模出现实世界中更多领域里错综复杂的信息关系,让计算机服务这些领域成为可能。

本文将和大家聊聊树的基本概念,以及树的物理存储结构以及实现。

2. 基本概念

数据结构的研究主要是从 2 点出发:

当数据之间存在一对多关系时,可以使用树来描述。如公司组织结构、家庭成员关系……
1.png

完整的树结构除了需要描述出数据信息,还需要描述数据与数据之间的关系。树结构中,以节点作为数据的具体形态,作为数据之间关系的具体形态。

也可以说树是由很多节点以及组成的集合。

如果一棵树没有任何节点,则称此树为空树。如果树不为空,则此树存在唯一的根节点(root),根节点是整棵树的起点,其特殊之处在于没有前驱节点。如上图值为董事长的节点。

除此之外,树中的节点与节点之间会存在如下关系:

如下图所示的 T 树 。

11.png

可以理解为T1T2子树组成。

12.png

T1、T2又可以认为是由它的子节点为根节点的子子树组成,以此类推,一直到叶节点为止。

树的相关概念:

树的类型:

13.png

3. 物理存储

可以使用邻接矩阵邻接表的形式存储树。

3.1 邻接矩阵存储

邻接矩阵是顺序表存储方案。

3.1.1 思路流程

2.png

3.png

4.png

5.png

矩阵记录了结点之间的双向(父到子,子到父)关系,最终看到是一个对称的稀疏矩阵。可以只存储上三角或下三角区域的信息,并可以对矩阵进行压缩存储。

邻接矩阵存储优点是实现简单、查询方便。但是,如果不使用压缩算法,空间浪费较大。

3.1.2 编码实现

现采用邻接矩阵方案实现对如下树的具体存储:

14.png

struct TreeNode{
	//节点的编号  
	int code;
	//节点上的值
	int data; 
}; 
class Tree {
	private:
		int size=7;
		vector<TreeNode> treeNodes;
		//使用矩阵存储节点之间的关系,矩阵第一行第一列不存储信息
		int matrix[7][7];
		//节点编号,为了方便,从 1 开始
		int idx=1;
	public:
		Tree() {
		}
		//初始根节点
		Tree(char root) {
			cout<<3<<endl;
			for(int  r=1; r<this->size; r++) {
				for(int c=1; c<this->size; c++) {
					this->matrix[r][c]=0;
				}
			}
			TreeNode node= {this->idx,root};
			this->treeNodes.push_back(node);
			//节点的编号由内部指定
			this->idx++;
		}
        //获取到根节点
		TreeNode getRoot() {
			return this->treeNodes[0];
		}
		//添加新节点
		int addVertex(char val) {
			if (this->idx>=this->size)
				return 0;
			TreeNode node= {this->idx,val};
			this->treeNodes.push_back(node);
			//返回节点编号
			return this->idx++;;
		}

		/*
		* 添加节点之间的关系
		*/
		bool addEdge(int from,int to) {
			char val;
			//查找编号对应节点是否存在
			if (isExist(from,val) && isExist(to,val)) {
				//建立关系
				this->matrix[from][to]=1;
                  //如果需要,可以打开双向关系
				//this->matrix[to][from]=1;
			}
		}
         //根据节点编号查询节点
		bool isExist(int code,char & val) {
			for(int i=0; i<this->treeNodes.size(); i++) {
				if (this->treeNodes[i].code==code) {
					val=this->treeNodes[i].data;
					return true;
				}
			}
			return false;
		}
		//输出节点信息
		void showAll() {
			cout<<"矩阵信息"<<endl;
			for(int  r=1; r<this->size; r++) {
				for(int c=1; c<this->size; c++) {
					cout<<this->matrix[r][c]<<" ";
				}
				cout<<endl;
			}
			cout<<"所有节点信息:"<<endl;
			for(int i=0; i<this->treeNodes.size(); i++) {
				TreeNode tmp=this->treeNodes[i];
				cout<<"节点:"<<tmp.code<<"-"<<tmp.data<<endl;
				//以节点的编号为行号,在列上扫描子节点
				char val;
				for(int j=1; j<this->size; j++ ) {
					if(this->matrix[tmp.code][j]!=0) {
						isExist(j,val);
						cout<<"\t子节点:"<<j<<"-"<<val<<endl;
					}
				}
			}
		}
};

测试代码:

int main() {
	//通过初始化根节点创建树
	Tree tree('A');
	TreeNode root=tree.getRoot();
	int codeB= tree.addVertex('B');
	tree.addEdge(root.code,codeB);
	int	codeC= tree.addVertex('C');
	tree.addEdge(root.code,codeC);
	int	codeD= tree.addVertex('D');
	tree.addEdge(codeB,codeD);
	int	codeE= tree.addVertex('E');
	tree.addEdge(codeC,codeE);
	int	codeF= tree.addVertex('F');
	tree.addEdge(codeC,codeF);
	tree.showAll();
}

标签:C++,spdlog,,光速入门,logger,简单,最快,c语言,方式,程序,退出,进阶篇,参数值,文档,gmock
来源: