之前写了一篇关于二叉树的概要介绍,里面包括了二叉树的创建等相关代码,这一篇文章主要来详细的对二叉树的创建讲解一下~
参考之前的文章二叉树的概要介绍
首先,定义一下关于二叉树的结点信息
typedef struct BtNode
{
struct BtNode* leftchild;
struct BtNode* rightchild;
ElemType data;
}BtNode, *BinaryTree;
这是篇文章所要分析的树
接下来进入正题,我们首先为大家呈现的是
一、二叉数的递归遍历
1、二叉树的递归中序遍历
void InOder(struct BtNode* p)
{
if (p != NULL)
{
InOder(p->leftchild);
printf("%c", p->data);
InOder(p->rightchild);
}
}
2、二叉树的递归先序遍历
void PreOder(struct BtNode* p)
{
if (p != NULL)
{
printf("%c", p->data);
PreOder(p->leftchild);
PreOder(p->rightchild);
}
}
3、二叉数的递归后续遍历
void LsOder(struct BtNode* p)
{
if (p != NULL)
{
LsOder(p->leftchild);
LsOder(p->rightchild);
printf("%c", p->data);
}
}
实现原理:
首先进入循环,递归进入结点A的左子树B;再递归进入结点B的左子树C;结点C的左子树为空,则打印结点C,回退到结点B,打印B;接着递归进入结点B的右子树D,结点D的左子树为空,打印结点D,回退到结点B;B的递归完成,回退到A,打印结点A…依次类推。
二、二叉树的非递归遍历
1、非递归中序遍历
void NiceInOrder(struct BtNode* ptr)
{
if (ptr == NULL) return;
stack<struct BtNode*> st;
while (!st.empty() || ptr != NULL)
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top(); st.pop();
cout << ptr->data << " ";
ptr = ptr->rightchild;
}
cout << endl;
}
本代码的关键在于while (!st.empty() || ptr != NULL)这个循环。因为当我们把C入栈过后它的ptr为空,但是这时的栈并不为空,所以再次进入循环;
当把A出栈过后,因为ptr右子树还有没有遍历到的结点,所以ptr != NULL进入循环,循环操作。
2、非递归后序遍历
特点:该结点的左边访问完了右边访问完了才应该打印该结点
所以要有一个标记结点来判定右子树有被访问过没有,如果访问过了就打印该结点。
void NicePastOrder(struct BtNode* ptr)
{
if (NULL == ptr) return;
stack<struct BtNode*> st;
struct BtNode* tag = NULL;
while (!st.empty() || ptr != NULL)
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top(); st.pop();
if (ptr->rightchild == NULL || ptr->rightchild == tag)
{
cout << ptr->data << " ";
tag = ptr;
ptr = NULL;
}
else
{
st.push(ptr);
ptr = ptr->rightchild;
}
}
cout << endl;
}
3、非递归前序遍历
前序遍历只需要先把右子树入栈再把左子树入栈,最后打印即可
void NicePreOrder(struct BtNode* ptr)
{
if (ptr == NULL) return;
stack<struct BtNode*> st;
st.push(ptr);
while (!st.empty())
{
ptr = st.top(); st.pop();
cout << ptr->data << " ";
if (ptr->rightchild != NULL)
{
st.push(ptr->rightchild);
}
if (ptr->leftchild != NULL)
{
st.push(ptr->leftchild);
}
}
cout << endl;
}
三、利用栈实现非递归遍历
1、非递归后序遍历
用数字标记结点入栈次数
struct StkNode
{
struct BtNode* pnode;
int popnum;
public:
StkNode(struct BtNode* p = NULL) :pnode(p), popnum(0) {}
};
void StkNicePastOrder(struct BtNode* ptr)
{
if (ptr == NULL) return;
stack<StkNode> st;
st.push(StkNode(ptr));
while (!st.empty())
{
StkNode node = st.top(); st.pop();
if (++node.popnum == 3)
{
cout << node.pnode->data << " ";
}
else
{
st.push(node);
if (node.popnum == 1 && node.pnode->leftchild != NULL)
{
st.push(StkNode(node.pnode->leftchild));
}
else if (node.popnum == 2 && node.pnode->rightchild != NULL)
{
st.push(StkNode(node.pnode->rightchild));
}
}
}
cout << endl;
}
2、非递归中序遍历
void StkNiceInOrder(struct BtNode* ptr)
{
if (ptr == NULL) return;
stack<StkNode> st;
st.push(StkNode(ptr));
while (!st.empty())
{
StkNode node = st.top(); st.pop();
if (++node.popnum == 2)
{
cout << node.pnode->data << " ";
if (node.pnode->rightchild != NULL)
{
st.push(StkNode(node.pnode->rightchild));
}
}
else
{
st.push(node);
if (node.popnum == 1 && node.pnode->leftchild != NULL)
{
st.push(StkNode(node.pnode->leftchild));
}
}
}
cout << endl;
}
四、层次遍历
队列实现。根结点入队,队列不为空就打印,再依次入队左右节点
void LevelOrder(struct BtNode* ptr)
{
if (NULL == ptr) return;
queue<struct BtNode*> qu;
qu.push(ptr);
while (!qu.empty())
{
ptr = qu.front(); qu.pop();
cout << ptr->data << " ";
if (ptr->leftchild != NULL)
{
qu.push(ptr->leftchild);
}
if (ptr->rightchild != NULL)
{
qu.push(ptr->rightchild);
}
}
cout << endl;
}
五、“工”字型遍历
一个栈一个队列共同实现
void LevelOrder2(struct BtNode* ptr)
{
if (NULL == ptr) return;
stack<struct BtNode*> qua;
queue<struct BtNode*> qub;
qua.push(ptr);
while (!qua.empty() || !qub.empty())
{
while(!qua.empty())
{ ptr = qua.top(); qua.pop();
cout << ptr->data << " ";
if (ptr->rightchild != NULL)
{
qub.push(ptr->rightchild);
}
if (ptr->leftchild != NULL)
{
qub.push(ptr->leftchild);
}
}
while (!qub.empty())
{
ptr = qub.front(); qub.pop();
cout << ptr->data << " ";
if (ptr->rightchild != NULL)
{
qua.push(ptr->rightchild);
}
if (ptr->leftchild != NULL)
{
qua.push(ptr->leftchild);
}
}
}
cout << endl;
}