代码先锋网 代码片段及技术文章聚合

基础算法——关于树的整理

1. 有根树表达

   使用左子右兄弟法(left-child right-sibling representation)表示树,各个结点具有一以下信息:

  • 结点u的父结点
  • 结点u的最左侧结点
  • 结点u的右侧紧邻的兄弟结点
//有根数的表达
#include <iostream>
using namespace std;
#define MAX 100005
#define NTL -1

struct Node {
	int p,l,r;
};

Node T[MAX];
int n,D[MAX];

void print(int u){
	int i,c;
	cout<<"node"<<u<<": ";
	cout<<"parent = "<<T[u].p<<", ";
	cout<<"depth = "<<D[u]<<", ";
	
	if(T[u].p==NTL)
		cout<<"root, ";
	else if(T[u].l==NTL)
		cout<<"leaf, ";
	else 
		cout<<"internal node, ";
		
	cout<<"[";
	
	for(int i=0,c=T[u].l;c!=NTL;i++,c=T[c].r){
		if(i)
			cout<<", ";
		cout<<c;
	}
	cout<<"]"<<endl;
}

//递归求深度
int rec(int u, int p){
	D[u]=p;
	if(T[u].r!=NTL)
		rec(T[u].r, p);//右侧兄弟设置为相同深度 
	if(T[u].l!=NTL)
		rec(T[u].l,p+1);// 左侧子节点深度+1 
} 

int main(){
	int i,j,d,v,c,l,r;
	cin>>n;
	for(i=0;i<n;i++)
		T[i].p=T[i].l=T[i].r=NTL;
	
	for(i=0;i<n;i++){
		cin>>v>>d;
		for(j=0;j<d;j++){
			cin>>c;
			if(j==0)
				T[v].l=c;
			else
				T[l].r=c;
			l = c;
			T[c].p=v;
		}
	} 
	for(i=0;i<n;i++)
		if(T[i].p==NTL)
			r=i;
	
	rec(r,0);
	
	for(i=0;i<n;i++)
		print(i);
	
	return 0;
} 


2. 二叉树表达

   需要表达出以下的信息:

  • u的结点标号
  • u的深度
  • u的父节点
  • u的高
  • u的兄弟结点
  • 结点的种类
  • u的子结点数
// 二叉树表达 
#include <iostream>
//#incluce <cstdio>
#include <stdio.h>
using namespace std;
#define NTL -1
#define MAX 1000

struct Node{
	int parent,left,right;
}; 
Node T[MAX];
int n, D[MAX], H[MAX];

int getDepth(int u){
	int d=0;
	while(T[u].parent!=NTL){
		u = T[u].parent;
		d++;
	}
	return d;
}

//void setDepth(int u,int p){
//	int D[u] = p;
//	if(T[u].right!=NTL)
//		setDepth(T[u].right, p);// 计算右侧兄弟节点 
//	if(T[u].left!=NTL)
//		setDepth(T[u],left, p+1);// 计算左侧子节点 
//}

void setDepth(int u, int d){
	if(u==NTL)
		return;
	D[u] = d;
	int deg=0;
	setDepth(T[u].left, d+1);
	setDepth(T[u].right,d+1);
	printf("degree = %d, ", deg);
	printf("depth = %d, ", D[u]);
	printf("heigth = %d, ", H[u]);
	
	if(T[u].parent == NTL)
		printf("root\n");
	else if(T[u].left == NTL&&T[u].right == NTL )
		printf("left\n");
	else
		printf("internal node\n");
} 

int setHeight(int u){
	int h1=0,h2=0;
	if(T[u].left!=NTL)
		h1 = setHeight(T[u].left)+1;
	if(T[u].right!=NTL)
		h2 = setHeight(T[u].right)+1;
	
	return H[u] = (h1>h2?h1:h2);
}

//返回结点u的兄弟结点
int getSibling(int u){
	if(T[u].parent == NTL)
		return NTL;
	
} 

void print(int u){
	printf("node %d: ", u);
	printf("parent = %d, ", T[u].parent);
	printf("sibling = %d, ", getSibling(u));
	int deg = 0;
	if(T[u].left != NTL)
		deg++;
	if(T[u].right != NTL)
		deg++;
}

int main(){
	
	int v,l,r,root=0;
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		T[i].parent = NTL;
	
	for(int i=0;i<n;i++){
		cin>>v>>l>>r;
		T[v].left = l;
		T[v].right = r;
		if(l != NTL)
			T[l].parent = v;
		if(r != NTL)
			T[r].parent = r;
	}
	
	for(int i=0;i<n;i++)
		if(T[i].parent == NTL)
			root = i;
	
	setDepth(root, 0);
	setHeight(root);
	
	for(int i=0;i<n;i++)
		print(i);
	
	return 0;
} 

3. 树的遍历

   树的遍历分三种方式:

  • 前序遍历:根结点——左子树——右子树
  • 中序遍历:左子树——根结点——右子树
  • 后序遍历:左子树——右子树——根结点
//二叉树的遍历
/*测试数据
9
0 1 4
1 2 3
2 -1 -1
3 -1 -1
4 5 8
5 6 7
6 -1 -1
7 -1 -1
8 -1 -1 

*/
#include <iostream>
#define MAX 10000
#define NTL -1
using namespace std;

struct Node{
	int p,l,r; 
};
Node T[MAX];
int n;

//前序遍历 
void preParse(int u){
	if(u == NTL)
		return;
	cout<<u<<" ";
	preParse(T[u].l);
	preParse(T[u].r);
}

//中序遍历
void inParse(int u){
	if(u==NTL)
		return;
	inParse(T[u].l);
	cout<<u<<" ";
	inParse(T[u].r); 
} 

//后序遍历
void postParse(int u){
	if(u==NTL)
		return;
	postParse(T[u].l);
	postParse(T[u].r);
	cout<<u<<" ";
} 


int main(){
	int i,v,l,r,root;
	
	cin>>n;
	for(int i=0;i<n;i++)//初始化 
		T[i].p = NTL;
	
	for(int i=0;i<n;i++){
		cin>>v>>l>>r;
		T[v].l = l;
		T[v].r = r;
		if(l!=NTL)
			T[l].p = v;
		if(r!=NTL)
			T[r].p = v;
	}
	
	for(int i=0;i<n;i++)//寻找时树的根 
		if(T[i].p == NTL)
			root = i;
	
	cout<<"Preorder"<<endl;
	preParse(root);
	cout<<endl;
	cout<<"Inorder"<<endl;
	inParse(root);
	cout<<endl;
	cout<<"Postorder"<<endl;
	postParse(root);
	cout<<endl;
	
	return 0;
}

 

版权声明:本文为qq_41895747原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41895747/article/details/100606810

智能推荐

关于verilog的一些基础知识整理

*作者: Ian11122840 时间: 2010-9-27 09:04 * *标题: 菜鸟做设计必看!有关如何做设计的整体思路,以及能否综合的笔记 * *所谓综合,就是把描述语言转化成能硬件实现的电路,学verilog的时候,没有人给我说要不要考虑能否综合的问题~~~ * *看了5本书,居然没有一本书讲到能否综合,所以设计出来的程序完全不能用~~~ * 而且,书中都是讲语句的具体使用办法,例如a...

Xman整理篇___关于Python的基础内容(函数)

Python内置了很多函数,可以直接调用 要调用一个函数,需要知道函数的名称和参数,例如: abs(x):返回x的绝对值;  int():将其他数据类型转换为整数;  str():把其他类型转换成str cmp(x,y):2个参数,如果x<y,返回 -1,如果x>y,返回1,如果相等,返回0 在Python中定义一个函数使用def语句,依次写出函数名、括号,括号中的...

关于树的算法题(C++)

前段时间总结了一下关于树的算法,上传到博客,以后方便查看。 目录 二叉树的下一个节点 二叉树的镜像 对称二叉树 树的子结构 二叉树的路径 打印二叉树 重建二叉树 二叉搜索树第K大的节点 二叉搜索树变成双向链表 二叉搜索树的后序遍历 序列化二叉树 平衡二叉树 二叉树的下一个节点 二叉树的镜像 对称二叉树 树的子结构 二叉树的路径 打印二叉树 重建二叉树 二叉搜索树第K大的节点 二叉搜索树变成双向链表...

C数据结构于算法-基础整理-树-08:二叉排序树

0x01.二叉排序树概念 二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。它可以是一棵空树。 二叉排序树必须满足以下条件: 若它的左子树不为空,则左子树上所有结点的值均小于它的根结构的值。 若它的右子树不为空,则右子树上所有结点的值均大于它的根结构的值。 它的左右子树也分别为二叉排序树。 0x02.二叉排序树的结构 其实就是普...

C数据结构与算法-基础整理-树-10:赫夫曼树

0x01.关于赫夫曼树 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 0x02.相关概念 路径:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径。 路径长度:路径上的分支称为路径长度 结点的权:给每个结点赋予的具有特殊含义的值称为...

猜你喜欢

关于技术的整理

  * 计算机、通讯、数学等相关专业本科以上学历,3年以上JAVA/J2EE开发工作经验   * 精通Memcached、Smarty、Redis、MongoDB   * 精通HTML/CSS/JavaScript/Ajax/JQuery等相关技术   * 熟悉Apache/Nginx的配置和使用   * 数...

关于循环的整理。

循环结构 for循环 do….while 循环 while 循环 for循环 for(初始化语句;判断条件语句;控制条件语句){ 循环语句; } while 循环 while(判断条件语句){ 循环语句; 控制条件语句; } do….while 循环 do{ 循环语句; 控制条件语句; }while(判断条件语句); 三种循环的区别: do。。while循环必须先运行一...

关于数组的整理

Reference:关于vue更新数组项 VUE的数组变更方法 官方提供的变更方法有:(以下vue提供的方法均会修改原数组) push() pop() shift() unshift() splice() sort() reverse() 各方法的作用于返回值 push() 作用:将一个或多个元素添加到数组的末尾 返回值:该数组的新长度 unshift() 作用:将一个或多个元素添加到数组的开头 ...

算法基础——关于哈希结构的学习

哈希函数 什么是哈希函数?哈希函数是散列函数,具有这些特征: 有限输出,无限输入:常用的哈希函数中,MD5,输出0到264-1的值,而SHA-1输出0到2128-1的值。 没有任何随机成份:给定相同的输入,得到相同的输出,当然不同的输入也可能有相同的输出。所以会有哈希碰撞 疏密性质:不管输入如何,输出的分布是十分离散的,可以认为是均匀的分布。 利用哈希函数解决大数据问题 假定给40亿个整数,无符号...

算法整理 & 复习:字典树

字典树(trie树) 返回...