【数据结构】树 的基本代码

1. 树的表示法

  1. 广义表表示法
  2. 双亲表表示法
  3. 左孩子右兄弟表示法
  4. 孩子链表表示法
    本文采用孩子链表表示法

2. 树的基本结构及函数总览

template<class T>
class Tree
{
	T* NA;
	list<int>* HL;
	int root;
	int sizeN, sizeC;
	int maxN;
public:
	Tree(int n = 100) :root(-1), sizeN(0), sizeC(0), maxN(n)
	{
		NA = new T[n];
		HL = new list<int>[n];
	}
	~Tree() { delete[]NA; delete[]HL; }
	int Empty()const { return (sizeN == 0); }
	int Full()const { return (sizeN == maxN); }
	int SizeN() const{ return sizeN; }
	int SizeC() const{ return sizeC; }
	
	int FindNode(const T& node)const; //已知node找下标
	bool FindeNode(T& node, int pos)const; //已知下标返node
	
	bool InsertN(const T& node); //插入节点
	bool InsertC(const T& parent, const T& child); //插入孩子
	
	void ReadTree(const char* filename); //重载输入运算符
	void WriteTree(const char* filename); //重载输出运算符
    
    void BFS(list<T>& L)const; //广度优先遍历
	void DFS(list<T>& L, int t)const; //深度优先遍历(先根遍历)

    template<class T>//在模板函数的声明前要加此句
	friend istream& operator>>(istream& istr, Tree<T>& t);//重载输入运算符
	template<class T>//在模板函数的声明前要加此句
	friend ostream& operator<<(ostream& ostr, const Tree<T>& t);
};

3. 树的基本操作

//已知node找下标
template<class T>
int Tree<T>::FindNode(const T& node)const
{
	for (int i = 0; i < sizeN; i++)
		if (NA[i] == node)
			return i;
	return -1;
}
//已知下标返node
template<class T>
bool Tree<T>:: FindeNode(T& node, int pos)const
{
	if (pos<0||pos >= sizeN)
		return 0;
	node = NA[pos];
	return 1;
}

//插入节点
template<class T>
bool Tree<T>::InsertN(const T& node)
{
	if (sizeN == maxN)
		return 0;
	NA[sizeN] = node;
	sizeN++;
	return 1;
}
//插入孩子
template<class T>
bool Tree<T>::InsertC(const T& parent, const T& child)
{
	int pi = FindNode(parent), cj = FindNode(child);
	if (pi == -1 || cj == -1 || pi == cj)
		return 0;
	HL[pi].insert(HL[pi].end(), cj);
	sizeC++;
	return 1;
}

//重载输入运算符
template <class T>
istream& operator>>(istream& istr, Tree<T>& t)
{
	int i;
	int n;
	char str[50];
	T parent, child;
	istr >> str >> n;
	istr >> str >> parent;
	t.InsertN(parent);
	t.root = t.sizeN - 1;  //reson
	istr >> str;
	for (i = 1; i <n ;++i)
	{
		istr >> child;
		t.InsertN(child);
	}
	istr >> str >> n;
	for (i = 1; i <= n; ++i)
	{
		istr >> parent >> child;
		t.InsertC(parent, child);
	}
	return istr;
}
//重载输出运算符
template <class T>
ostream& operator<<(ostream& ostr, const Tree<T>& t)
{
	for (int i = 0; i < t.sizeN; i++)
	{
		ostr << i << '-' << t.NA[i] << ':';
		list<int>::iterator first = t.HL[i].begin(), last = t.HL[i].end();
		for (; first != last; ++first)
			ostr << '(' << *first << ')' << ' ';
		ostr << endl;
	}
	return ostr;
}

4. 树的遍历

4.1 广度优先遍历
//广度优先遍历
template<class T>
void Tree<T>:: BFS(list<T>& L)const
{
	if (sizeN == 0)
		return;
	int t;
	queue<int> Q;
	Q.push(root);
	list<int>::const_iterator first, last;
	while (Q.empty())
	{
		t = Q.front();
		Q.pop();
		L.push_back(NA[t]);
		first = HL[t].begin();
		last = HL[t].end();
		for (; first != last; first++)
		{
			Q.push(*first);
		}
	}
}
4.2 深度优先遍历(先根遍历)
//深度优先遍历(先根遍历)
template<class T>
void Tree<T>::DFS(list<T>& L,int t)const
{
	if (t<0||t>=sizeN)
		return;
	L.push_back(t);
	list<int>::const_iterator first, last;
	first = HL[t].begin();
	last = HL[t].end();
	for (; first != last; first++)
		DFS(L, *first);
}

5. 基本代码汇总及测试

private部分和友元函数的申明曾出现过问题,现已解决
具体看帖:https://bbs.csdn.net/topics/394772306

#include <iostream>
#include <list>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;

template<class T>
class Tree
{
//public://
	T* NA;
	list<int>* HL;
	int root;
	int sizeN, sizeC;
	int maxN;
public:
	Tree(int n = 100) :root(-1), sizeN(0), sizeC(0), maxN(n)
	{
		NA = new T[n];
		HL = new list<int>[n];
	}
	~Tree() { delete[]NA; delete[]HL; }
	int Empty()const { return (sizeN == 0); }
	int Full()const { return (sizeN == maxN); }
	int SizeN() const{ return sizeN; }
	int SizeC() const{ return sizeC; }/
	int FindNode(const T& node)const;
	bool FindeNode(T& node, int pos)const;
	
	bool InsertN(const T& node);
	bool InsertC(const T& parent, const T& child);
	
	void ReadTree(const char* filename);
	void WriteTree(const char* filename);

	void BFS(list<T>& L)const;
	void DFS(list<T>& L, int t)const;
	
	template<class T>在模板函数的声明前加此句
	friend istream& operator>>(istream& istr, Tree<T>& t);//重载输入运算符
	template<class T>///在模板函数的声明前加此句
	friend ostream& operator<<(ostream& ostr, const Tree<T>& t);
};

//已知node找下标
template<class T>
int Tree<T>::FindNode(const T& node)const
{
	for (int i = 0; i < sizeN; i++)
		if (NA[i] == node)
			return i;
	return -1;
}
//已知下标返node
template<class T>
bool Tree<T>:: FindeNode(T& node, int pos)const
{
	if (pos<0||pos >= sizeN)
		return 0;
	node = NA[pos];
	return 1;
}

//插入节点
template<class T>
bool Tree<T>::InsertN(const T& node)
{
	if (sizeN == maxN)
		return 0;
	NA[sizeN] = node;
	sizeN++;
	return 1;
}
//插入孩子
template<class T>
bool Tree<T>::InsertC(const T& parent, const T& child)
{
	int pi = FindNode(parent), cj = FindNode(child);
	if (pi == -1 || cj == -1 || pi == cj)
		return 0;
	HL[pi].insert(HL[pi].end(), cj);
	sizeC++;
	return 1;
}

//重载输入运算符
template <class T>
istream& operator>>(istream& istr, Tree<T>& t)
{
	int i;
	int n;
	char str[50];
	T parent, child;
	istr >> str >> n;
	istr >> str >> parent;
	t.InsertN(parent);
	t.root = t.sizeN - 1;  //reson
	istr >> str;
	for (i = 1; i <n ;++i)
	{
		istr >> child;
		t.InsertN(child);
	}
	istr >> str >> n;
	for (i = 1; i <= n; ++i)
	{
		istr >> parent >> child;
		t.InsertC(parent, child);
	}
	return istr;
}

//重载输出运算符
template <class T>
ostream& operator<<(ostream& ostr, const Tree<T>& t)
{
	for (int i = 0; i < t.sizeN; i++)///
	{
		ostr << i << '-' << t.NA[i] << ':';
		list<int>::iterator first = t.HL[i].begin(), last = t.HL[i].end();
		for (; first != last; ++first)
			ostr << '(' << *first << ')' << ' ';
		ostr << endl;
	}
	return ostr;
}

//广度优先遍历
template<class T>
void Tree<T>:: BFS(list<T>& L)const
{
	if (sizeN == 0)
		return;
	int t;
	queue<int> Q;
	Q.push(root);
	list<int>::const_iterator first, last;
	while (!Q.empty())
	{
		t = Q.front();
		Q.pop();
		L.push_back(NA[t]);
		first = HL[t].begin();
		last = HL[t].end();
		for (; first != last; first++)
		{
			Q.push(*first);
		}
	}
}

//深度优先遍历(先序遍历)
template<class T>
void Tree<T>::DFS(list<T>& L,int t)const
{
	if (t<0||t>=sizeN)
		return;
	L.push_back(NA[t]);
	list<int>::const_iterator first, last;
	first = HL[t].begin();
	last = HL[t].end();
	for (; first != last; first++)
		DFS(L, *first);
}

template<class T>
void Tree<T>::ReadTree(const char* filename)
{
	ifstream fin;
	fin.open(filename, ios::in || ios::_Nocreate);
	if (!fin)
	{
		cout << "1cannot open " << filename << endl;
		exit(1);
	}
	fin >> *this;
	
}

template<class T>
void Tree<T>::WriteTree(const char* filename)
{
	ofstream fout;
	fout.open(filename, ios::out);
	if (!fout)
	{
		cout << "2cannot open " << filename << endl;		
		exit(1);
	}
	fout << *this;
}

template <class iterator>
void Display(iterator first,iterator last)
{
	for (; first != last; first++)
		cout << *first << "   ";
}

int main()
{
	Tree<char> a(20);
	
	/法一:
	/*ifstream fin;
	fin.open("D:\\VS代码\\treein.txt", ios::in || ios::_Nocreate);
	if (!fin)
	{
		cout << "1cannot open D:\\VS代码\\treein.txt. \n " << endl;
		exit(1);
	}
	fin >> a;
	ofstream fout;
	fout.open("D:\\VS代码\\treeout.txt", ios::out);
	if (!fout)
	{
		cout << "2cannot open D:\\VS代码\\treeout.txt. \n";
		exit(1);
	}
	fout << a;*/
	//法二;
	/*
	cin >> a;
	cout << a;//在屏幕上确认是否为预想结果
	return 0;
	*/
	///法三:
	a.ReadTree("D:\\VS代码\\treein.txt");
	a.WriteTree("D:\\VS代码\\treeout.txt");
	
	list<char> L;
	
	a.DFS(L,0);
	cout << "DFS called" << endl;
	Display(L.begin(), L.end());
	cout << endl;
	L.clear();
	
	a.BFS(L);
	cout << "BFS called" << endl;
	Display(L.begin(), L.end());
	cout << endl;
	L.clear();

}

6. 八皇后

自己写八皇后出现过一些问题,已解决,详细看帖:https://bbs.csdn.net/topics/394782997

#include<iostream>
#include<conio.h>//getch
#include <stdlib.h>//exit
using namespace std;

//八皇后
void display(const int* Y, int n)
{
	int k;
	int x, y;
	static int total = 1;
	for (y = 0; y < n; y++)
	{
		if (y % n == 0)
			cout << total++ << endl;
		for (x = 0; x< n; x++)
		{
			if (x== Y[y]) //不要再把=当==!
				cout << " @ ";
			else
				cout << " # ";
		}
		cout << endl;
	}
	cout << "Press any key to see" << endl;
	k=_getch(); //若想去除: 警告C6031 返回值被忽略 : “_getch”, 则如大佬所言,把 getch返回值赋给一个变量
}
void Queen(int y)
{
	int x;
	static int A[22], B[22], C[22], Y[8];
	if (y < 0 || y>8)
	{
		cout << "y ellage";
		exit(1);
	}
	if (y == 8)
	{
		display(Y,8);
		return;
	}
	for (x = 0; x < 8; x++)
	{
		if (!A[x + 7] && !B[x + y + 7] && !C[x - y + 7])
		{
			Y[y] = x;
			A[x + 7] = B[x + y + 7] = C[x - y + 7] = 1;
			Queen(y + 1);
			A[x + 7] = B[x + y + 7] = C[x - y + 7] = 0;
		}
	}
}

int main()
{
	Queen(0);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值