一般树性结构

一.一般树结点和树的ADT

template <typename E>
class GTNode{
private:
	E value;
	GTNode* parent;
	GTNode* leftmostChild;
	GTNode* rightSibling;
public:
	GTNode() { parent = leftmostChild = rightSibling = NULL; }
	GTNode(E v, GTNode<E>* lc = NULL, GTNode<E>* rs = NULL) {
		value = v; leftmostChild = lc; rightSibling = rs;
	}
	E value() { return value; }
	GTNode* parent() { return parent; }
	GTNode* leftmostChild() { return leftmostChild; }
	GTNode* rightSibling() { return rightSibling; }
	bool isLeaf() { return leftmostChild == NULL; }
	void setValue(E& v) { value = v; }
	void insertFirst(GTNode<E>*);
	void insertNext(GTNode<E>*);
	void removeFirst();
	void removeNext();
};

template <typename E>
class GenTree {
private:
	GTNode<E>* root;
	
public:
	void clear();
	GTNode<E>* getroot() { return root; }
	void newroot(E&, GTNode<E>*, GTNode<E>*);
	void print() { printhelp(root); }
	
};


二.一般树的遍历
和二叉树类似,但是除了中序遍历对一般树没有太大的意义
树的遍历用的还是递归方法,和二叉树类似
如:利用树的遍历进行打印
template <typename E>
void printhelp(GTNode<E>* rt) {
	if (rt->leftmostChild == NULL) cout << "Leaf node : ";
	else cout << "Inner node : ";
	cout << rt->value();
	for (GTNode<E>* start = rt->leftmostChild(); start != NULL; start = start->rightSibling())
		printhelp(start);
}
又:利用树的遍历,数出树所有的结点
template <typename E>
void getCount(GTNode<E>* rt) {
	if (rt == NULL) return 0;
	int count = 1;
	for (GTNode<E>* temp = rt->leftmostChild(); temp != NULL; temp = temp->rightSibling())
	{
		count += getCount(temp);
	}
	return count;
}

三. 父指针表示法

(1)父指针表示法:对每个结点只保存一个指针域指向父结点,特别适合解决判断两个结点是否在同一个树中的问题。

(2)父指针表示法常用的两种操作:FIND和UNION

FIND:对给定的一个结点,找到它的根节点
UNION:合并两个集合


代码实现:
template <typename E>
class GenTree {
private:
	int* array;
	int size;
	int FIND(int) const;
	const int ROOT = -1;
public:
	GenTree(int sz) {
		size = sz;
		array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = ROOT;
	}
	~GenTree() {
		delete[] array;
	}
	bool differ(int a, int b) {
		return FIND(a) != FIND(b);
	}
	
	int FIND(int curr)const {
		while (array[curr] != ROOT) curr = array[curr];
		return curr;
	}
	void UNION(int a, int b) {
		int root1 = array[a];
		int root2 = array[b];
		if (root1 != root2)
			root2 = root1;
	}

};



(3)解决一个问题:如何降低合并操作时树的高度?
方法一:重量权衡合并规则:把结点少的树和结点多的树合并时,把结点少的树的父指针指向结点多的树
方法二:路径压缩:在FIND操作时,把当前结点所有的祖先结点的父结点都设置为根结点,这样做能够使得树的高度最低,使得FIND操作的复杂度非常接近常数


四. 实现树的方法:
(1)子结点表表示法:
(2)左子结点/右兄弟结点表示法:
(3)动态结点表示法:
(4)动态左子结点/右兄弟结点表示法:




五. 顺序表示法:
存储一系列结点的值,其中包含了尽可能少但是对于重建树必不可少的信息


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值