基本组成单位:二叉树节点,边对应于节点间的相互引用。
二叉树节点的模板类:
template <typename T>
struct BinNode {
//成员
T data;
BinNodePosi(T) parent; BinNodePosi(T) lc; BinNodePosi(T) rc;
int height;
//构造函数
BinNode() : parent(NULL), lc(NULL), rc(NULL), height(0){}
BinNode(T e, BinNodePosi(T) p = NULL, BinNodePosi(T) lc = NULL, BinNodePosi(T) rc = NULL, int h = 0):
data(e), parent(p), lc(lc), rc(rc), hright(h) {}
//操作接口
int size();//当前节点后代总数
BinNodePosi(T) insertAsLc (T const&); //作为左子树插入
BinNodePosi(T) insertAsRc (T const&); //作为右子树插入
BinNodePosi(T) succ; // 当前节点的直接后继
template<typename VST> void travLevel(VST&); //层次遍历
template<typename VST> void travPre(VST&); //先序遍历
template<typename VST> void travIn(VST&); //中序遍历
template<typename VST> void travPOost(VST&); //后序遍历
//比较器、判等器
bool operator < (BinNode const& bn){
return data < bn.data;
}
bool operator == (BinNode const& bn){
return data == bn.data;
}
};
template <typename T>
BinNodePosi(T) BinNode<T> :: insertAsLc (T const& e){
return lc = new BinNode(e, this);
}
template <typename T>
BinNodePosi(T) BinNode<T> :: insertAsRc (T const& e){
return rc = new BinNode(e, this);
}
二叉树的遍历:
(一)递归式遍历
1)先序遍历:先访问根节点,在访问左子树,再访问右子树。
template <typename T, typename VST>
void travPre_R (BinNodePosi(T) x, VST& visit){
if(!x) return ;
visit(x->data);
travPre_R(x->lc, visit);
travPre_R(x->rc, visit);
}
2)中序遍历:左——>根——>右
template <typename T, typename VST>
void travIn_R (BinNodePosi(T) x, VST& visit){
if(!x) return ;
travIn_R(x->lc, visit);
visit(x->data);
travIn_R(x->rc, visit);
}
3)后序遍历:左——>右——>根
template <typename T, typename VST>
void travPost_R (BinNodePosi(T) x, VST& visit){
if(!x) return ;
travPost_R(x->lc, visit);
travPost_R(x->rc, visit);
visit(x->data);
}
(二)迭代式遍历
1)先序遍历:
迭代版本1:
template <typename T, typename VST>
void travPre_I1(BinNodePosi(T) x, VST& visit){
Stack <BinNodePosi(T)> S;
if(x) S.push(x);
while(!S.empty()){
x = S.pop(); visit(x->data);
id(HasRChild(*x)) S.push(x->rChild);
id(HasLChild(*x)) S.push(x->lChild);
}
}
迭代版本2:
template <typename T, typename VST>
static void visitAlongLeftBranch(BinNodePosi(T) x, VSY& visit, Stack <BinNodePosi(T) &S0){
while (x){
visit(x->data);
S.push(x->rChild);
x = x->lChild;
}
}
template <typename T, typename VST>
void travPre_I2 (BinNodePosi(T) x, VST& visit){
Stack <BinNodePosi(T)> S;
while (true){
visitAlongLeftBranch(x, visit, S);
if (S.empty()) break;
x = S.pop();
}
}
2)中序遍历
template <typename T>
static void goAlongLeftBranch(BinNodePosi(T) x, Stack<BinNodePosi(T)>& S){
while (x){
S.push(x);
x = x->lc;
}
}
template <typename T, typename VST>
void travIn_I1 (BinNodePosi(T) x, VST& visit){
Stack <BinNodePosi(T)> S;
while (true){
goAlongLeftBranch(x, S);
if (S.empty()) break;
x = S.pop(); visit(x->data);
x = x->rc;
}
}
//与先序遍历类似,只不过是从底向上访问。将入栈的每个左子树的节点视为根节点并访问,再转向右子树
PS.邓老师的数据结构难度还是有的,尤其是基础的语言不太熟悉的情况下,其实这本书学到这里,感觉更重要的是,不断地发现问题的规律并进行优化改进。我打算继续看完视频,写完这本书上的代码,最后估计还是会回来看很多遍的。