多叉树的二叉树表示法(左儿子右兄弟)

  • Post author:
  • Post category:其他


在二叉树的基础上,我们可以扩展出任意多个叉的树。即,多叉树。然而,此时又面临着另外一个问题:

  • 当孩子结点无限制时,我们并不知道

    预先要分配多少个属性

    ,且当

    仅有少数元素拥有多个子节点

    时,将会造成大量的空间浪费。

此时,提出了一种新的表示形式:




l

e

f

t

c

h

i

l

d

r

i

g

h

t

s

i

b

l

i

n

g

r

e

p

r

e

s

e

n

t

a

t

i

o

n

left-child \quad right-sibling \quad representation






l


e


f


t













c


h


i


l


d




r


i


g


h


t













s


i


b


l


i


n


g




r


e


p


r


e


s


e


n


t


a


t


i


o


n







左孩子右兄弟表示法

对于任意一个结点T,其仅包含两个指针:


  1. T.left-child

    ,指向T结点的最左侧子节点。

  2. T.right-sibling

    ,指向T右侧最邻近的兄弟结点。

特别的,当二者不存在时,相应的指针皆为空,即

NIL

。该方法只需要



O

(

n

)

O(n)






O


(


n


)





空间来存储含



n

n






n





个结点的树。

由于其与二叉树的相似性,故又叫

树的二叉树表示法

在此,给出一个样例:

左孩子右兄弟树

该样例旨在为下述算法提供一个参考。



相关算法



深度

对于该种树而言,任意一个节点和其右节点的深度相同。也就意味着对于一个节点T,其高度为要么

和右子树高度相同

,要么

比左子树低一层

。从叶子节点向上递归,即可得出最大深度。即:

int Height(Tree& t){
	if(t == nullptr) return 0;
	return Height(t->left) + 1 > Height(t->right) ? Height(t->left) + 1 : Height(t->right);
} 



叶子节点数

基于二叉树中的定义,

叶子节点

是没有子节点的节点。在该种表示方法中,即

左指针为空

的节点(某一层的最后一个叶子节点右子树也为空,故只看左指针就行)。对于一个节点的叶子节点数,即:

int Count(Tree& t){
	if(t == nullptr) return 0;
	if(t->left == nullptr) return 1;
	return Count(t->left) + Count(t->right); 
}



遍历



先序遍历

先序遍历,对于某个节点而言,其

左指针



第一个子节点

。向左指针递归即寻找孩子,回溯时输出右指针的兄弟。与二叉树的先序遍历完全一致。

void preOrder(Tree& t){
	if(t == nullptr) return;
	cout<<t->val<<" ";	//输出值
	TreeNode* p = t->left;
	while(p != nullptr){
		preOrder(p);
		p = p->right;
	}	
}



后序遍历

后序遍历过程中,对于一个节点,应该打印其左指针和全部右侧的节点后才打印该节点,即回溯时才打印当前节点。

void PostOrder(Tree& t){
	if(t == nullptr) return;
	TreeNode* p = t->left;
	while(p != nullptr){
		PostOrder(p); 	//递归找“根”
		p = p->right;
	}
	cout<<t->val<<" ";
} 



层序遍历

层序遍历,即类似于广度优先算法。对于一个节点,当打印左节点时,应将其右侧所有兄弟节点都打印再去下一层。打印其兄弟节点时,保留其左节点,即其子节点的兄弟。基于此,也可统计出每层的

宽度

。有注释的几行即为相应的宽度统计。

void levelOrder(Tree& t){
	if(t == nullptr) return;
	queue<TreeNode*> q;
	TreeNode* p;
    int max = INT_MIN; //宽度
	q.push(t);
	while(!q.empty()){
		int width = q.size();		
		for(int i = 0;i < width;i ++){
			p = q.front();
			q.pop();
			cout<<p->val<<" ";
			p = p->left;
			while(p != nullptr){
				q.push(p);
				p = p->right;
			}
		}
        max = max > width ? max: width;        //一层遍历结束 统计宽度
		cout<<endl;
	}
    return max;			//返回宽度
}

搭建了个

个人blog

,感兴趣的话来玩呀。



版权声明:本文为weixin_46065476原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。