读书笔记之:数据结构,算法与应用(3)
第8章 二叉树和其他树
1. 术语:
树和二叉树的术语,如高度、深度、层、根、叶子、子节点、父节点和兄弟节点。
4种常用的二叉树遍历方法:前序遍历,中序遍历,后序遍历和按层遍历。
2. 线性数据结构,表数据结构,层次数据结构
3. 二叉树与树的根本区别
4. 二叉树的特性
5. 二叉树遍历方法
在前三种方法中,每个节点的左子树在其右子树之前遍历。这三种遍历的区别在于对同一个节点在不同时刻进行访问。在进行前序遍历时,每个节点是在其左右子树被访问之前进行访问的;在中序遍历时,首先访问左子树,然后访问子树的根节点,最后访问右子树。在后序遍历时,当左右子树均访问完之后才访问子树的根节点。
在逐层遍历过程中,按从顶层到底层的次序访问树中元素,在同一层中,从左到右进行访问。由于遍历中所使用的数据结构是一个队列而不是栈,因此写一个按层遍历的递归程序很困难。
6. 二叉树遍历一个常用问题:数学表达式的形式
当对一棵数学表达式树进行中序,前序和后序遍历时,就分别得到表达式的中缀、前缀和后缀形式。中缀( infix)形式即平时所书写的数学表达式形式,在这种形式中,每个二元操作符(也就是有两个操作数的操作符)出现在左操作数之后,右操作数之前。在使用中缀形式时,可能会产生一些歧义。例如, x+y×z 可以理解为 (x+y)×z 或x+(y×z)。为了避免这种歧义,可
对操作符赋于优先级并采用优先级规则来分析中缀表达式。在完全括号化的中缀表达式中,每个操作符和相应的操作数都用一对括号括起来。更甚者把操作符的每个操作数也都用一对括号括起来。如 ((x)+(y)),((x)+((y)*(z)))和(((x)+(y))*((y)+(z)))*(w)。
在后缀(postfix)表达式中,每个操作符跟在操作数之后,操作数按从左到右的顺序出现。在前缀( p r e f i x)表达式中,操作符位于操作数之前。在前缀和后缀表达式中不会存在歧义。因此,在前缀和后缀表达式中都不必采用括号或优先级。从左到右或从右到左扫描表达式并采用操作数栈,可以很容易确定操作数和操作符的关系。若在扫描中遇到一个操作数,把它压入堆栈,若遇到一个操作符,则将其与栈顶的操作数相匹配。把这些操作数推出栈,由操作符执行相应的计算,并将所得结果作为操作数压入堆栈。
1. 术语:
树和二叉树的术语,如高度、深度、层、根、叶子、子节点、父节点和兄弟节点。
4种常用的二叉树遍历方法:前序遍历,中序遍历,后序遍历和按层遍历。
2. 线性数据结构,表数据结构,层次数据结构
3. 二叉树与树的根本区别
4. 二叉树的特性
5. 二叉树遍历方法
在前三种方法中,每个节点的左子树在其右子树之前遍历。这三种遍历的区别在于对同一个节点在不同时刻进行访问。在进行前序遍历时,每个节点是在其左右子树被访问之前进行访问的;在中序遍历时,首先访问左子树,然后访问子树的根节点,最后访问右子树。在后序遍历时,当左右子树均访问完之后才访问子树的根节点。
在逐层遍历过程中,按从顶层到底层的次序访问树中元素,在同一层中,从左到右进行访问。由于遍历中所使用的数据结构是一个队列而不是栈,因此写一个按层遍历的递归程序很困难。
6. 二叉树遍历一个常用问题:数学表达式的形式
当对一棵数学表达式树进行中序,前序和后序遍历时,就分别得到表达式的中缀、前缀和后缀形式。中缀( infix)形式即平时所书写的数学表达式形式,在这种形式中,每个二元操作符(也就是有两个操作数的操作符)出现在左操作数之后,右操作数之前。在使用中缀形式时,可能会产生一些歧义。例如, x+y×z 可以理解为 (x+y)×z 或x+(y×z)。为了避免这种歧义,可
对操作符赋于优先级并采用优先级规则来分析中缀表达式。在完全括号化的中缀表达式中,每个操作符和相应的操作数都用一对括号括起来。更甚者把操作符的每个操作数也都用一对括号括起来。如 ((x)+(y)),((x)+((y)*(z)))和(((x)+(y))*((y)+(z)))*(w)。
在后缀(postfix)表达式中,每个操作符跟在操作数之后,操作数按从左到右的顺序出现。在前缀( p r e f i x)表达式中,操作符位于操作数之前。在前缀和后缀表达式中不会存在歧义。因此,在前缀和后缀表达式中都不必采用括号或优先级。从左到右或从右到左扫描表达式并采用操作数栈,可以很容易确定操作数和操作符的关系。若在扫描中遇到一个操作数,把它压入堆栈,若遇到一个操作符,则将其与栈顶的操作数相匹配。把这些操作数推出栈,由操作符执行相应的计算,并将所得结果作为操作数压入堆栈。
7. 抽象数据结构:二叉树
要删除一棵二叉树,需要删除其所有节点。可以通过后序遍历在访问一个节点时,把其删除。也就是说先删除左子树,然后右子树,最后删除根。
9. 计算高度
通过进行后序遍历,可以得到二叉树的高度。首先得到左子树的高度 hl,然后得到右子树的高度hr。此时,树的高度为:
max{hl,hr} + 1
二叉树节点代码:
View Code
#ifndef _BINARYTREENODE_H_
#define _BINARYTREENODE_H_
template <class T>
class BinaryTree;
class Booster;
template <class T>
class BinaryTreeNode{
friend class BinaryTree<T>;
friend class Booster;
friend void PlaceBoosters(BinaryTreeNode<Booster>*);
public:
BinaryTreeNode(){
lchild=rchild=0;
}
BinaryTreeNode(const T& e){
data=e;
lchild=rchild=0;
}
BinaryTreeNode(const T& e,BinaryTreeNode<T>* l,BinaryTreeNode<T>* r){
data=e;
lchild=l;
rchild=r;
}
T getData(){
return data;
}
BinaryTreeNode<T>* getLChild(){
return lchild;
}
BinaryTreeNode<T>* getRChild(){
return rchild;
}
void setData(const T& e){
data=e;
}
void setLChild(BinaryTreeNode<T>* l){
lchild=l;
}
void setRChild(BinaryTreeNode<T>* r){
rchild=r;
}
private:
T data;
BinaryTreeNode<T> *lchild;
BinaryTreeNode<T> *rchild;
};
#endif
#define _BINARYTREENODE_H_
template <class T>
class BinaryTree;
class Booster;
template <class T>
class BinaryTreeNode{
friend class BinaryTree<T>;
friend class Booster;
friend void PlaceBoosters(BinaryTreeNode<Booster>*);
public:
BinaryTreeNode(){
lchild=rchild=0;
}
BinaryTreeNode(const T& e){
data=e;
lchild=rchild=0;
}
BinaryTreeNode(const T& e,BinaryTreeNode<T>* l,BinaryTreeNode<T>* r){
data=e;
lchild=l;
rchild=r;
}
T getData(){
return data;
}
BinaryTreeNode<T>* getLChild(){
return lchild;
}
BinaryTreeNode<T>* getRChild(){
return rchild;
}
void setData(const T& e){
data=e;
}
void setLChild(BinaryTreeNode<T>* l){
lchild=l;
}
void setRChild(BinaryTreeNode<T>* r){
rchild=r;
}
private:
T data;
BinaryTreeNode<T> *lchild;
BinaryTreeNode<T> *rchild;
};
#endif
数据类型二叉树类:
View Code
#ifndef _BINARYTREE_H_
#define _BINARYTREE_H_
#include <iostream>
#include <queue>
#include "BinaryTreeNode.h"
int _count;
template <class T>
class BinaryTree{
public:
BinaryTree():root(0){}
~BinaryTree(){}
bool IsEmpty()const{
return root?false:true;
}
bool Root(T& x)const;
void MakeTree(const T& elem,BinaryTree<T>& left,BinaryTree<T>& right);
void BreakTree(T& elem,BinaryTree<T>& left,BinaryTree<T>& right);
void PreOrder(void(*Visit)(BinaryTreeNode<T>* u)){
PreOrder(Visit,root);
}
void InOrder(void(*Visit)(BinaryTreeNode<T>* u)){
InOrder(Visit,root);
}
void PostOrder(void(*Visit)(BinaryTreeNode<T>* u)){
PostOrder(Visit,root);
}
void LevelOrder(void(*Visit)(BinaryTreeNode<T>*u));
void PreOutput(){
PreOrder(Output,root);
std::cout<<std::endl;
}
void InOutput(){
InOrder(Output,root);
std::cout<<std::endl;
}
void PostOutput(){
PostOrder(Output,root);
std::cout<<std::endl;
}
void LevelOutput(){
LevelOrder(Output);
std::cout<<std::endl;
}
void Delete(){
PostOrder(Free,root);
root=0;
}
int Height()const{
return Height(root);
}
int Size(){
_count=0;
PreOrder(Add1,root);
return _count;
}
private:
BinaryTreeNode<T> *root;
void PreOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
void InOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
void PostOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
static void Output(BinaryTreeNode<T>* t){
std::cout<<t->data<<' ';
}
static void Free(BinaryTreeNode<T>* t){
delete t;
}
int Height(BinaryTreeNode<T> *t)const;
static void Add1(BinaryTreeNode<T>* t){
_count++;
}
};
template <class T>
bool BinaryTree<T>::Root(T& x)const
{
if(root){
x=root->data;
return true;
}
else
return false;
}
template <class T>
void BinaryTree<T>::MakeTree(const T& elem,BinaryTree<T>& left,BinaryTree<T>& right)
{
root=new BinaryTreeNode<T>(elem,left.root,right.root);
left.root=right.root=0;
}
template <class T>
void BinaryTree<T>::BreakTree(T& elem,BinaryTree<T>& left,BinaryTree<T>& right)
{
if(!root)
throw "BadInput";
elem=root->data;
left.root=root->lchild;
right.root=root->rchild;
delete root;
root=0;
}
template <class T>
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
Visit(t);
PreOrder(Visit,t->lchild);
PreOrder(Visit,t->rchild);
}
}
template <class T>
void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
InOrder(Visit,t->lchild);
Visit(t);
InOrder(Visit,t->rchild);
}
}
template <class T>
void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
PostOrder(Visit,t->lchild);
PostOrder(Visit,t->rchild);
Visit(t);
}
}
template <class T>
void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T>*u )){
std::queue<BinaryTreeNode<T>*> qu;
BinaryTreeNode<T>* t;
qu.push(root);
while(!qu.empty()){
t=qu.front();
if(t){
Visit(t);
if(t->lchild)
qu.push(t->lchild);
if(t->rchild)
qu.push(t->rchild);
}
qu.pop();
}
}
template <class T>
int BinaryTree<T>::Height(BinaryTreeNode<T> *t)const{
if(!t)
return 0;
int hl=Height(t->lchild);
int hr=Height(t->rchild);
if(hl>hr)
return ++hl;
else
return ++hr;
}
#endif
#define _BINARYTREE_H_
#include <iostream>
#include <queue>
#include "BinaryTreeNode.h"
int _count;
template <class T>
class BinaryTree{
public:
BinaryTree():root(0){}
~BinaryTree(){}
bool IsEmpty()const{
return root?false:true;
}
bool Root(T& x)const;
void MakeTree(const T& elem,BinaryTree<T>& left,BinaryTree<T>& right);
void BreakTree(T& elem,BinaryTree<T>& left,BinaryTree<T>& right);
void PreOrder(void(*Visit)(BinaryTreeNode<T>* u)){
PreOrder(Visit,root);
}
void InOrder(void(*Visit)(BinaryTreeNode<T>* u)){
InOrder(Visit,root);
}
void PostOrder(void(*Visit)(BinaryTreeNode<T>* u)){
PostOrder(Visit,root);
}
void LevelOrder(void(*Visit)(BinaryTreeNode<T>*u));
void PreOutput(){
PreOrder(Output,root);
std::cout<<std::endl;
}
void InOutput(){
InOrder(Output,root);
std::cout<<std::endl;
}
void PostOutput(){
PostOrder(Output,root);
std::cout<<std::endl;
}
void LevelOutput(){
LevelOrder(Output);
std::cout<<std::endl;
}
void Delete(){
PostOrder(Free,root);
root=0;
}
int Height()const{
return Height(root);
}
int Size(){
_count=0;
PreOrder(Add1,root);
return _count;
}
private:
BinaryTreeNode<T> *root;
void PreOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
void InOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
void PostOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t);
static void Output(BinaryTreeNode<T>* t){
std::cout<<t->data<<' ';
}
static void Free(BinaryTreeNode<T>* t){
delete t;
}
int Height(BinaryTreeNode<T> *t)const;
static void Add1(BinaryTreeNode<T>* t){
_count++;
}
};
template <class T>
bool BinaryTree<T>::Root(T& x)const
{
if(root){
x=root->data;
return true;
}
else
return false;
}
template <class T>
void BinaryTree<T>::MakeTree(const T& elem,BinaryTree<T>& left,BinaryTree<T>& right)
{
root=new BinaryTreeNode<T>(elem,left.root,right.root);
left.root=right.root=0;
}
template <class T>
void BinaryTree<T>::BreakTree(T& elem,BinaryTree<T>& left,BinaryTree<T>& right)
{
if(!root)
throw "BadInput";
elem=root->data;
left.root=root->lchild;
right.root=root->rchild;
delete root;
root=0;
}
template <class T>
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
Visit(t);
PreOrder(Visit,t->lchild);
PreOrder(Visit,t->rchild);
}
}
template <class T>
void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
InOrder(Visit,t->lchild);
Visit(t);
InOrder(Visit,t->rchild);
}
}
template <class T>
void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T>*u),BinaryTreeNode<T>* t)
{
if(t){
PostOrder(Visit,t->lchild);
PostOrder(Visit,t->rchild);
Visit(t);
}
}
template <class T>
void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T>*u )){
std::queue<BinaryTreeNode<T>*> qu;
BinaryTreeNode<T>* t;
qu.push(root);
while(!qu.empty()){
t=qu.front();
if(t){
Visit(t);
if(t->lchild)
qu.push(t->lchild);
if(t->rchild)
qu.push(t->rchild);
}
qu.pop();
}
}
template <class T>
int BinaryTree<T>::Height(BinaryTreeNode<T> *t)const{
if(!t)
return 0;
int hl=Height(t->lchild);
int hr=Height(t->rchild);
if(hl>hr)
return ++hl;
else
return ++hr;
}
#endif
二叉树测试代码:
View Code
8. 删除二叉树#include <iostream>
#include "BinaryTree.h"
using namespace std;
int count=0;
BinaryTree<int> a,x,y,z;
template<class T>
void ct(BinaryTreeNode<T> *t){
count++;
}
void test1(){
y.MakeTree(10,a,a);
z.MakeTree(20,a,a);
x.MakeTree(30,y,z);
y.MakeTree(40,x,a);
y.PreOrder(ct);
cout<<count<<endl;
y.PreOutput();
y.InOutput();
y.PostOutput();
y.LevelOutput();
}
void test2(){
y.MakeTree(1,a,a);
z.MakeTree(2,a,a);
x.MakeTree(3,y,z);
y.MakeTree(4,x,a);
cout << "Preorder sequence is ";
y.PreOutput();
cout << "Inorder sequence is ";
y.InOutput();
cout << "Postorder sequence is ";
y.PostOutput();
cout << "Level order sequence is ";
y.LevelOutput();
cout << "Number of nodes = ";
cout << y.Size() << endl;
cout << "Height = ";
cout << y.Height() << endl;
y.PreOrder(ct);
cout << "Count of nodes is " << count << endl;
}
int main(){
test2();
}
#include "BinaryTree.h"
using namespace std;
int count=0;
BinaryTree<int> a,x,y,z;
template<class T>
void ct(BinaryTreeNode<T> *t){
count++;
}
void test1(){
y.MakeTree(10,a,a);
z.MakeTree(20,a,a);
x.MakeTree(30,y,z);
y.MakeTree(40,x,a);
y.PreOrder(ct);
cout<<count<<endl;
y.PreOutput();
y.InOutput();
y.PostOutput();
y.LevelOutput();
}
void test2(){
y.MakeTree(1,a,a);
z.MakeTree(2,a,a);
x.MakeTree(3,y,z);
y.MakeTree(4,x,a);
cout << "Preorder sequence is ";
y.PreOutput();
cout << "Inorder sequence is ";
y.InOutput();
cout << "Postorder sequence is ";
y.PostOutput();
cout << "Level order sequence is ";
y.LevelOutput();
cout << "Number of nodes = ";
cout << y.Size() << endl;
cout << "Height = ";
cout << y.Height() << endl;
y.PreOrder(ct);
cout << "Count of nodes is " << count << endl;
}
int main(){
test2();
}
要删除一棵二叉树,需要删除其所有节点。可以通过后序遍历在访问一个节点时,把其删除。也就是说先删除左子树,然后右子树,最后删除根。
9. 计算高度
通过进行后序遍历,可以得到二叉树的高度。首先得到左子树的高度 hl,然后得到右子树的高度hr。此时,树的高度为:
max{hl,hr} + 1
10.设置信号放大器
代码如下:
View Code
#include <iostream>
#include "BinaryTree.h"
using namespace std;
int tolerance = 3;
class Booster{
friend int main();
friend void PlaceBoosters(BinaryTreeNode<Booster>*);
public:
void Output(ostream& out)const{
out<<boost<<' '<<D<<' '<<d<<' ';
}
private:
int D,d;
bool boost;
};
ostream& operator<<(ostream& out,const Booster& x)
{
x.Output(out);
return out;
}
void PlaceBoosters(BinaryTreeNode<Booster>* x){
BinaryTreeNode<Booster> *y=x->getLChild();
int degr;
Booster btr;
btr.D=0;
x->data.D=0;
if(y){
degr=(y->getData()).D+(y->getData()).d;
if(degr>tolerance){
y->data.boost=true;
x->data.D=y->data.d;
}
else
x->data.D=degr;
}
y=x->getRChild();
if(y){
degr=y->data.D+y->data.d;
if(degr>tolerance) {
y->data.boost=true;
degr=y->data.d;
}
if(x->data.D<degr)
x->data.D=degr;
}
}
BinaryTree<Booster> T, U, V, W, X, Y;
int main(void)
{
Booster a, b;
a.d = 2; a.D =0; a.boost = 0;
b.d=1; b.D=0; b.boost = 0;
U.MakeTree(a,X,X);
V.MakeTree(b,U,X);
U.MakeTree(a,X,X);
W.MakeTree(a,U,X);
b.d=3;
U.MakeTree(b,V,W);
V.MakeTree(a,X,X);
b.d=3;
W.MakeTree(b,X,X);
Y.MakeTree(a,V,W);
W.MakeTree(a,X,X);
T.MakeTree(b,Y,W);
b.d=0;
V.MakeTree(b,T,U);
V.PostOrder(PlaceBoosters);
V.PostOutput();
}
#include "BinaryTree.h"
using namespace std;
int tolerance = 3;
class Booster{
friend int main();
friend void PlaceBoosters(BinaryTreeNode<Booster>*);
public:
void Output(ostream& out)const{
out<<boost<<' '<<D<<' '<<d<<' ';
}
private:
int D,d;
bool boost;
};
ostream& operator<<(ostream& out,const Booster& x)
{
x.Output(out);
return out;
}
void PlaceBoosters(BinaryTreeNode<Booster>* x){
BinaryTreeNode<Booster> *y=x->getLChild();
int degr;
Booster btr;
btr.D=0;
x->data.D=0;
if(y){
degr=(y->getData()).D+(y->getData()).d;
if(degr>tolerance){
y->data.boost=true;
x->data.D=y->data.d;
}
else
x->data.D=degr;
}
y=x->getRChild();
if(y){
degr=y->data.D+y->data.d;
if(degr>tolerance) {
y->data.boost=true;
degr=y->data.d;
}
if(x->data.D<degr)
x->data.D=degr;
}
}
BinaryTree<Booster> T, U, V, W, X, Y;
int main(void)
{
Booster a, b;
a.d = 2; a.D =0; a.boost = 0;
b.d=1; b.D=0; b.boost = 0;
U.MakeTree(a,X,X);
V.MakeTree(b,U,X);
U.MakeTree(a,X,X);
W.MakeTree(a,U,X);
b.d=3;
U.MakeTree(b,V,W);
V.MakeTree(a,X,X);
b.d=3;
W.MakeTree(b,X,X);
Y.MakeTree(a,V,W);
W.MakeTree(a,X,X);
T.MakeTree(b,Y,W);
b.d=0;
V.MakeTree(b,T,U);
V.PostOrder(PlaceBoosters);
V.PostOutput();
}
11. 树与二叉树(详细介绍)
12. 在线等价类问题
(1)利用数组解决
View Code
//Online equivalence class functions using arrays
#include <iostream>
using namespace std;
int *E, n;
void Initialize(int n)
{// Initialize n classes with one element each.
E = new int [n + 1];
for (int e = 1; e <= n; e++)
E[e] = e;
}
void Union(int i, int j)
{// Union the classes i and j.
for (int k = 1; k <= n; k++)
if (E[k] == j) E[k] = i;
}
int Find(int e)
{// Find the class that contains element i.
return E[e];
}
int main(void)
{
n = 10;
Initialize(n);
Union(1,2);
Union(3,4);
Union(1,3);
cout << '1' << ' ' << Find(1) << ' ' << '2' << ' ' << Find(2) << endl;
cout << '3' << ' ' << Find(3) << ' ' << '4' << ' ' << Find(4) << endl;
cout << '5' << ' ' << Find(5) << ' ' << '6' << ' ' << Find(6) << endl;
}
#include <iostream>
using namespace std;
int *E, n;
void Initialize(int n)
{// Initialize n classes with one element each.
E = new int [n + 1];
for (int e = 1; e <= n; e++)
E[e] = e;
}
void Union(int i, int j)
{// Union the classes i and j.
for (int k = 1; k <= n; k++)
if (E[k] == j) E[k] = i;
}
int Find(int e)
{// Find the class that contains element i.
return E[e];
}
int main(void)
{
n = 10;
Initialize(n);
Union(1,2);
Union(3,4);
Union(1,3);
cout << '1' << ' ' << Find(1) << ' ' << '2' << ' ' << Find(2) << endl;
cout << '3' << ' ' << Find(3) << ' ' << '4' << ' ' << Find(4) << endl;
cout << '5' << ' ' << Find(5) << ' ' << '6' << ' ' << Find(6) << endl;
}
(2)利用树解决
代码如下:
View Code
//Simple tree solution to union-find problem
//
#include <iostream>
using namespace std;
int *parent;
void Initialize(int n){
parent=new int[n+1];
for(int e=1;e<=n;e++)
parent[e]=0;
}
int Find(int e){
while(parent[e])
e=parent[e];
return e;
}
void Union(int i,int j){
parent[j]=i;
}
int main(void)
{
Initialize(10);
Union(1,2);
Union(3,4);
Union(1,3);
cout << "Find(1) = " << Find(1) << " Find(2) = " << Find(2) << endl;
cout << "Find(3) = " << Find(3) << " Find(4) = " << Find(4) << endl;
cout << "Find(5) = " << Find(5) << " Find(6) = " << Find(6) << endl;
}
//
#include <iostream>
using namespace std;
int *parent;
void Initialize(int n){
parent=new int[n+1];
for(int e=1;e<=n;e++)
parent[e]=0;
}
int Find(int e){
while(parent[e])
e=parent[e];
return e;
}
void Union(int i,int j){
parent[j]=i;
}
int main(void)
{
Initialize(10);
Union(1,2);
Union(3,4);
Union(1,3);
cout << "Find(1) = " << Find(1) << " Find(2) = " << Find(2) << endl;
cout << "Find(3) = " << Find(3) << " Find(4) = " << Find(4) << endl;
cout << "Find(5) = " << Find(5) << " Find(6) = " << Find(6) << endl;
}
(3)利用重量或高度规则来提高性能
代码如下:
View Code
// union/find with weighting rule
#include <iostream>
#include <cstdlib>
using namespace std;
int *parent;
bool *root;
void Initialize(int n)
{// One element per set/class/tree.
root = new bool[n+1];
parent = new int[n+1];
for (int e = 1; e <= n; e++) {
parent[e] = 1;
root[e] = true;}
}
int Find(int e)
{// Return root of tree containing e.
while (!root[e])
e = parent[e]; // move up one level
return e;
}
int Find_compact(int e)
{// Return root of tree containing e.
// Compact path from e to root.
int j = e;
// find root
while (!root[j])
j = parent[j];
// compact
int f = e; // start at e
while (f != j) {// f is not root
int pf = parent[f];
parent[f] = j; // move f to level 2
f = pf; // f moves to old parent
}
return j;
}
void Union(int i, int j)
{// Combine trees with roots i and j.
// Use weighting rule.
if (parent[i] < parent[j]) {
// i becomes subtree of j
parent[j] += parent[i];
root[i] = false;
parent[i] = j; }
else {// j becomes subtree of i
parent[i] += parent[j];
root[j] = false;
parent[j] = i;}
}
int main(void)
{
Initialize(10);
Union(1,2);
Union(3,4);
Union(1,3);
cout << '1' << ' ' << Find(1) << ' ' << '2' << ' ' << Find(2) << endl;
cout << '3' << ' ' << Find(3) << ' ' << '4' << ' ' << Find(4) << endl;
cout << '5' << ' ' << Find(5) << ' ' << '6' << ' ' << Find(6) << endl;
}
#include <iostream>
#include <cstdlib>
using namespace std;
int *parent;
bool *root;
void Initialize(int n)
{// One element per set/class/tree.
root = new bool[n+1];
parent = new int[n+1];
for (int e = 1; e <= n; e++) {
parent[e] = 1;
root[e] = true;}
}
int Find(int e)
{// Return root of tree containing e.
while (!root[e])
e = parent[e]; // move up one level
return e;
}
int Find_compact(int e)
{// Return root of tree containing e.
// Compact path from e to root.
int j = e;
// find root
while (!root[j])
j = parent[j];
// compact
int f = e; // start at e
while (f != j) {// f is not root
int pf = parent[f];
parent[f] = j; // move f to level 2
f = pf; // f moves to old parent
}
return j;
}
void Union(int i, int j)
{// Combine trees with roots i and j.
// Use weighting rule.
if (parent[i] < parent[j]) {
// i becomes subtree of j
parent[j] += parent[i];
root[i] = false;
parent[i] = j; }
else {// j becomes subtree of i
parent[i] += parent[j];
root[j] = false;
parent[j] = i;}
}
int main(void)
{
Initialize(10);
Union(1,2);
Union(3,4);
Union(1,3);
cout << '1' << ' ' << Find(1) << ' ' << '2' << ' ' << Find(2) << endl;
cout << '3' << ' ' << Find(3) << ' ' << '4' << ' ' << Find(4) << endl;
cout << '5' << ' ' << Find(5) << ' ' << '6' << ' ' << Find(6) << endl;
}