1. 树的表示法
- 广义表表示法
- 双亲表表示法
- 左孩子右兄弟表示法
- 孩子链表表示法
本文采用孩子链表表示法
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;
}