在学数据结构教程,参照书中对于节点结构体的定义,尝试用自己的思路递归实现,算是原创。
使用了模板、内联函数等等C++特性,因为想用。
/**
Ver 1. All Original
CreateTree in Recursion as all other func.
CreateTree Input: char s[] as para of func.
Func named "xxxxFunc()" is for other func to call,
DO NOT CALL "xxxxFunc()" directly;
Use "xxxx()" instead.
*/
#include <iostream>
#include <cstdlib> // malloc()
#include <algorithm> // max()
using namespace std;
const int MAXSONS = 10;
const int MAXLEN = 100;
typedef char ElemType;
struct TSonNode {
ElemType data;
TSonNode* sons[MAXSONS];
};
struct TSBroNode {
ElemType data;
TSBroNode* hb; // Horizonal bro
TSBroNode* vs; // Vertical son
};
ElemType str[MAXLEN];
int n=0; // Extern. Uses as str[n].
// A Tree looks like 1. "A", 2. "A(B)", 3. "A(B, C)"
// if no '(' then tree is 1.
// catch B, if find ',' after B, tree is 3.
// else tree is 2.
void MakeTreeFunc(TSonNode*& T, ElemType* s) {
int k=0; // T->sons[k]
T = (TSonNode*)malloc(sizeof(TSonNode));
T->data = s[n++];
for (int i=0; i<MAXSONS; ++i)
T->sons[i] = NULL;
if (s[n] == '(') {
n++; // n always points to a data before MakeTree
MakeTreeFunc(T->sons[k++], s);
while (s[n] == ',') {
n++;
MakeTreeFunc(T->sons[k++], s);
}
n++; // skips ')'
}
}
void MakeTreeFunc(TSBroNode*& T, ElemType* s) {
T = (TSBroNode*)malloc(sizeof(TSBroNode));
T->data = s[n++];
T->hb = T->vs = NULL;
if (s[n] == '(') {
n++;
MakeTreeFunc(T->vs, s);
}
if (s[n] == ',') {
n++;
MakeTreeFunc(T->hb, s);
} // As a node has only 2 links, more of ',' is for his bros.
else n++; // if not ',' then s[n] is ')', skip.
}
// Template to accept TSonNode or TSBroNode, re-init n=0;
template <typename F>
inline F* MakeTree(F*& T, ElemType* s) { MakeTreeFunc(T, s); n=0; return T; }
// default: create by TSonNode
inline TSonNode* MakeTree(ElemType* s) {
TSonNode* T;
MakeTreeFunc(T, s);
n=0;
return T;
}
// A Tree looks like 1. "A", 2. "A(B)", 3. "A(B, C)"
// always cout "A"
// if no son then tree is 1.
// else disp each son-tree.
// (son1, son2, ..., sonk)
void DispTreeFunc(TSonNode* T) {
if (T == NULL) return;
cout << T->data;
int k=0;
if (T->sons[k] != NULL) {
cout << '(';
while (1) {
DispTreeFunc(T->sons[k++]);
if (T->sons[k] == NULL)
break;
if (k < MAXSONS) cout << ',';
else break;
}
cout << ')';
}
}
// One node 2 links only
// Has son? Has h-bro?
void DispTreeFunc(TSBroNode* T) {
if (T == NULL) return;
cout << T->data;
if (T->vs != NULL) {
cout << '(';
DispTreeFunc(T->vs);
cout << ')';
}
if (T->hb != NULL) {
cout << ',';
DispTreeFunc(T->hb);
}
}
template <typename F>
inline void DispTree(F* T) { DispTreeFunc(T); cout<<endl; }
int TreeHeight(TSonNode* T) {
if (T == NULL) return 0;
int ans = 0;
for (int k=0; k<MAXSONS; ++k) {
if (T->sons[k] == NULL) break;
ans = max(ans, TreeHeight(T->sons[k]));
}
return ans + 1; // parent = MaxAmongSons + 1
}
int TreeHeight(TSBroNode* T) {
if (T == NULL) return 0;
int ans = 1;
if (T->vs != NULL) {
ans = TreeHeight(T->vs) + 1; // parent = son + 1
}
if (T->hb != NULL) { // son = MaxAmongBros
ans = max(ans, TreeHeight(T->hb));
}
return ans;
}
void DestroyTree(TSonNode*& T) {
if (T == NULL) return;
for (int i=0; i<MAXSONS; ++i) {
if (T->sons[i] != NULL)
DestroyTree(T->sons[i]);
else break;
}
free(T);
}
void DestroyTree(TSBroNode*& T) {
if (T == NULL) return;
if (T->hb != NULL) DestroyTree(T->hb);
if (T->vs != NULL) DestroyTree(T->vs);
free(T);
}
int main()
{
TSonNode* pts = NULL;
TSBroNode* ptsb = NULL;
cin >> str;
DispTree(MakeTree(pts, str)); // MakeTree returns Node*
cout << TreeHeight(pts) << endl;
DispTree(MakeTree(str)); // Makes TSonNode Tree without pts para
MakeTree(ptsb, str); // Using Template to shift between NodeType
DispTree(ptsb);
cout << TreeHeight(ptsb) << endl;
return 0;
}
/*
A(B(E,F),C(G(J)),D(H,I(K(N,O),L,M)))
>>>5
A(B,C(F,G,H),D,E(I,J))
>>>3
*/
第二个版本,前三个函数是不同的,后两个是书上的做法部分替换为STL的实现。整体上,采用了键盘输入,而不是第一版的从字符串传参数。
/*
Ver 2. Book-referred
The First 3 func are new to ver 1.
CreateTree with stack.
CreateTree Input: cin.get() from Keyboard,
therefore you can only create one tree at one input.
Func named "xxxxFunc()" is for other func to call,
DO NOT CALL "xxxxFunc()" directly;
Use "xxxx()" instead.
*/
#include <iostream>
#include <cstdlib> // malloc()
#include <algorithm>
#include <stack>
#include <utility> // pair, make_pair()
using namespace std;
const int MAXSONS = 10;
const int MAXLEN = 100;
typedef char ElemType;
struct TSonNode {
ElemType data;
TSonNode* sons[MAXSONS];
};
struct TSBroNode {
ElemType data;
TSBroNode* hb;
TSBroNode* vs;
};
// Recursion as ver 1.
// But substitute cin.get() for a char str[]
// Advantage: avoid external para int n.
void MakeTree_R(TSonNode*& T) {
int k=0;
T = (TSonNode*)malloc(sizeof(T));
T->data = cin.get();
for (int i=0; i<MAXSONS; ++i)
T->sons[i] = NULL;
if (cin.peek() == '(') {
cin.get();
MakeTree_R(T->sons[k++]);
while (cin.peek() == ',') {
cin.get();
MakeTree_R(T->sons[k++]);
}
cin.get();
}
}
TSonNode* MakeTree(TSonNode*& T) {
T = NULL;
TSonNode* p = NULL;
stack<pair<TSonNode*, int> > st; // == stack<struct node>
ElemType ch;
while ((ch = cin.get()) != '\n') {
switch (ch)
{
case '(':
st.push(make_pair(p, 0));
break;
case ',':
st.top().second++;
break;
case ')':
st.pop();
break;
default:
p = (TSonNode*)malloc(sizeof(TSonNode));
p->data = ch;
for (int i=0; i<MAXSONS; ++i) {
p->sons[i] = NULL;
}
if (T == NULL) T = p; // get first data
else st.top().first->sons[st.top().second] = p; // then always possess top node
break;
}
}
return T;
}
TSBroNode* MakeTree(TSBroNode*& T) {
T = NULL;
TSBroNode* p = NULL;
stack<pair<TSBroNode*, int> > st;
ElemType ch;
while ((ch = cin.get()) != '\n') {
switch (ch)
{
case '(':
st.push(make_pair(p, 0));
break;
case ',':
st.top().second++;
break;
case ')':
st.pop();
break;
default:
p = (TSBroNode*)malloc(sizeof(TSBroNode));
p->data = ch;
p->vs = NULL;
p->hb = NULL;
if (T == NULL) T = p;
else if (st.top().second == 0) {
st.top().first->vs = p;
} else {
TSBroNode* q = st.top().first->vs;
for (int i=1; i<st.top().second; i++) {
q = q->hb;
} //q moves SonNum - 1 rightward, to be left to p.
q->hb = p;
}
break;
}
}
return T;
}
void DispTreeFunc(TSonNode* T) {
if (T == NULL) return;
cout << T->data;
int k=0;
if (T->sons[k] != NULL) {
cout << '(';
while (1) {
DispTreeFunc(T->sons[k++]);
if (T->sons[k] == NULL)
break;
if (k < MAXSONS) cout << ',';
else break;
}
cout << ')';
}
}
void DispTreeFunc(TSBroNode* T) {
if (T == NULL) return;
cout << T->data;
if (T->vs != NULL) {
cout << '(';
DispTreeFunc(T->vs);
cout << ')';
}
if (T->hb != NULL) {
cout << ',';
DispTreeFunc(T->hb);
}
}
template <typename F>
inline void DispTree(F* T) { DispTreeFunc(T); cout<<endl; }
int TreeHeight(TSonNode* T) {
if (T == NULL) return 0;
int ans = 0;
for (int k=0; k<MAXSONS; ++k) {
if (T->sons[k] == NULL) break;
ans = max(ans, TreeHeight(T->sons[k]));
}
return ans + 1;
}
int TreeHeight(TSBroNode* T) {
if (T == NULL) return 0;
int ans = 1;
if (T->vs != NULL) {
ans = TreeHeight(T->vs) + 1;
}
if (T->hb != NULL) {
ans = max(ans, TreeHeight(T->hb));
}
return ans;
}
void DestroyTree(TSonNode*& T) {
if (T == NULL) return;
for (int i=0; i<MAXSONS; ++i) {
if (T->sons[i] != NULL)
DestroyTree(T->sons[i]);
else break;
}
free(T);
}
void DestroyTree(TSBroNode*& T) {
if (T == NULL) return;
if (T->hb != NULL) DestroyTree(T->hb);
if (T->vs != NULL) DestroyTree(T->vs);
free(T);
}
int main()
{
TSonNode* pst = NULL;
TSBroNode* psbt = NULL;
// MakeTree(pt);
// // DispTree(pt);
// MakeTree(pst);
// DispTree(pst);
// DestroyTree(pst);
MakeTree(psbt);
DispTree(psbt);
cout << TreeHeight(psbt) << endl;
DestroyTree(psbt);
return 0;
}
/*
A(B(E,F),C(G(J)),D(H,I(K,L,M)))
>>>4
*/
参考:《数据结构教程》