任意有根树的左孩子右兄弟表示法存储

算法导论:10.4-4

对一个含n个结点的任意有根树,写出一个O(n)时间的过程,输出其所有关键字。

该树以左孩子或兄弟表示法存储。

#ifndef _ROOTED_TREE_H_
#define _ROOTED_TREE_H_

/*****************************************************************
算法导论:10.4-4

对一个含n个结点的任意有根树,写出一个O(n)时间的过程,输出其所有关键字。
该树以左孩子或兄弟表示法存储。
******************************************************************/

#include <iostream>

template <class T>
class RootedTree
{
public:
	class Node{
	public:
		friend class RootedTree < T > ;
		Node *getLeftChild()const { return _leftChild; }
		Node *getRightSibiling()const{ return _rightSibiling; }
		T value;
	private:
		Node() :_parent(nullptr), _leftChild(nullptr), _rightSibiling(nullptr){}
		Node(const T& v) :_parent(nullptr), _leftChild(nullptr), _rightSibiling(nullptr), value(v){}
		Node* _parent;			// 指向本结点的父结点
		Node* _leftChild;		// 指向本结点的第一个子结点,如果没有子结点,则为 null
		Node* _rightSibiling;	// 指向本结点的下一个兄弟结点,如果之后没有兄弟结点,则为 null
	};

	RootedTree() :_root(nullptr){  }
	RootedTree(const T& v){ _root = new Node(v); }
	~RootedTree();

	// 向指定的根结点中增加子结点,返回第一个子结点的指针。
	Node* addChilds(Node*, const T*, size_t);
	inline Node* getRoot() const { return _root; }

	void print() const;

private:
	// 二叉树的根结点
	Node* _root;

	void freeNodes(const Node* root);
	void print(const Node*) const;
};

template <class T>
RootedTree<T>::~RootedTree(){
	// 释放所有结点所占空间
	if (_root)
		freeNodes(_root);
}

template <class T>
void RootedTree<T>::freeNodes(const Node* root){
	// 释放左孩子结点
	if (root->_leftChild)
		freeNodes(root->_leftChild);
	// 释放右兄弟结点
	if (root->_rightSibiling)
		freeNodes(root->_rightSibiling);
	// 释放本结点
	delete root;
}

template <class T>
typename RootedTree<T>::Node* RootedTree<T>::addChilds(Node* root, const T* elements, size_t size){
	if (size > 0){
		// 创建根结点的第一个子结点
		auto firstNode = new Node(elements[0]);
		firstNode->_parent = root;
		root->_leftChild = firstNode;
		Node* node = nullptr;
		for (size_t i = size - 1; i > 0; --i){
			auto sibiling = new Node(elements[i]);
			sibiling->_parent = root;
			sibiling->_rightSibiling = node;
			node = sibiling;
		}
		firstNode->_rightSibiling = node;
		return firstNode;
	}
	return nullptr;
}

template <class T>
void RootedTree<T>::print() const{
	if (_root) {
		print(_root);
	}
}

template <class T>
void RootedTree<T>::print(const Node* root) const{
	if (root){
		//// 输出它的父结点
		//if (root->_parent)
		//	std::cout << " [" << root->_parent->value << "] ";
		std::cout << root->value << " ";
		// 打印它之后的兄弟
		print(root->_rightSibiling);
		// 打印第一个子结点
		print(root->_leftChild);
	}
}

#endif

测试例程:

using namespace std;

int main(){
	int ia1[] = { 10, 20, 30, 40, 50, 60 };
	int ia2[] = {300, 310, 320};
	int ia3[] = {3000, 3100, 3200};
	int ia4[] = { 200, 210, 230, 240 };

	RootedTree<int> tree(0);

	auto child1 = tree.addChilds(tree.getRoot(), ia1, 6);
	auto child2 = tree.addChilds(child1->getRightSibiling()->getRightSibiling(), ia2, 3);
	auto child3 = tree.addChilds(child2, ia3, 3);
	tree.addChilds(child1->getRightSibiling(), ia4, 4);

	tree.print();
}
时间: 2024-11-08 20:22:11

任意有根树的左孩子右兄弟表示法存储的相关文章

UVa 11732 strcmp()函数(左孩子右兄弟表示法)

1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 8 const int maxn = 4000 * 1000 + 10; 9 int n; 10 long long ans; 11 12 struct Trie 13 { 14 int head[

左儿子右兄弟表示法

顾名思义 每个节点一个为儿子指针,一个为兄弟指针(在加个父亲) 这样就避免了儿子个数不均带来的问题 TOJ TOJ4077 用一个指针记录当前在哪个节点,需要注意的是可以有多个重名的文件,但是不能在一个目录下. 所以用文件名和其父亲节点作为一个文件的id(区分其他). #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm

UVa 11732 &quot;strcmp()&quot; Anyone? (左儿子右兄弟前缀树Trie)

题意:给定strcmp函数,输入n个字符串,让你用给定的strcmp函数判断字符比较了多少次. 析:题意不理解的可以阅读原题https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 字符串很多,又很长,如果按照题目的意思两两比较,肯定会TLE,所以要用前缀树(Trie)来解决,当然只是用简单的前缀树也会TLE的, 我们必须对其进行优化,看了

左儿子右兄弟Trie UVA 11732 strcmp() Anyone?

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 一边inser

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie)

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 开始先建树记录次数,然后再遍历统计,结果错了... 后面参考了Shoutmon巨巨的写法,一边insert一边统计. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

UVA11732 &quot;strcmp()&quot; Anyone?【左儿子右兄弟Trie】

LINK1 LINK2 题目大意 给你一些字符串,并定义了一个函数(具体见题面) 问你把任意两个字符串放到函数里面得到的值的和是多少 思路 该怎么统计答案呢? 每次考虑当前插入的串和所有已经插入过的串一起统计答案 然后考虑一下怎么统计,假设当前深度是dep 并且现在是u,即将向v移动指针 那么怎么同几当前这一层的答案呢? 所有在v的子树中的节点显然是不能在这一层统计答案的 所以就考虑统计和所有不在同一个子树的答案 具体实现很简单,读者自己思考吧 注意在每一次走到字符串的末尾的时候需要特判 和他相

48.输入任意正整数,编程判断该数是否为回文数(回文数是指从左到右读与从右到左读一样,如12321)

//1.输入一个数,将其每一位分离,并保存如一个数组 //2.判断数组最后录入的一位是第几位 //3.循环判断是否满足回问数的要求 #include<iostream> using namespace std; int main() { int n,temp; int k=0; int a[20]; cout<<"please input an number: "<<endl; cin>>n; for(int i=0;i<20;i+

二叉查找树——A1064.Complete Binary Search Tree(30) 构建完全二叉查找树,利用完全二叉查找树的性质:左孩子为2x ,右孩子为 2x + 1

#include <bits/stdc++.h> #include <stdio.h> #include <stdlib.h> #include <queue> using namespace std; const int maxn = 1010; int temp[maxn],initial[maxn],n; int ind; void inorder(int root){//中序遍历 if(root > n){ return; } inorder(

sql 内连接 外连接 左连接 右连接

1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.     内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 students和courses表中学生标识号相同的所有行.       2.外联接.外联接可以是左向外联接.右向外联接或完整外部联接.     在 FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:     1)LEFT  JOIN或LEFT OUTER JOIN     左向外联接的结果集包括  LEF