二叉树非递归遍历
先序
头结点入栈,每次循环顺着左路一直找到底,先打印结点,遇右压栈就可以了。
void PreOrderNorOP(pBTNode pRoot)
{
Stack s;
init(&s);
pushBack(&s, pRoot);
while (!isEmpty(&s)) {
pBTNode pCur = top(&s);
pop(&s);
while (pCur) {
printf("%c ", pCur->_data);
if (pCur->_pRight) {
pushBack(&s, pCur->_pRight);
}
pCur = pCur->_pLeft;
}
}
}
解法二:类似于层序遍历的写法
void PreOrderNor(pBTNode pRoot)
{
Stack s;
init(&s);
pushBack(&s, pRoot);
while (!isEmpty(&s)) {
pBTNode pCur = top(&s);
pop(&s);
printf("%c ", pCur->_data);
if (pCur->_pRight)
pushBack(&s, pCur->_pRight);
if (pCur->_pLeft)
pushBack(&s, pCur->_pLeft);
}
}
中序
用pCur指向当前处理的结点,向左找到底,压栈保存沿途路径。
void InOrderNor(pBTNode pRoot)
{
if (pRoot) {
Stack s;
init(&s);
pBTNode pCur = pRoot;
while (!isEmpty(&s) || pCur) {
//找到最左结点
while (pCur) {
pushBack(&s, pCur);
pCur = pCur->_pLeft;
}
//无左结点,打印出栈
pCur = top(&s);
printf("%c ", pCur->_data);
pop(&s);
pCur = pCur->_pRight;
}
}
}
后序
后序就比较麻烦了。只用一个pCur完成不了任务了,因为如果像中序最后一句返回当前栈顶元素的右孩子,而下次循环还需要判断栈顶(父节点)和右孩子的关系,就会造成死循环。
所以用三个指针。
pCur:迭代临时指针,每次找到左路最底的NULL。仅在遇右子树时改变。
pTop: 代码围绕栈顶元素来写。
pPre:记录上一个打印的结点。例如在C-》F的时候需要判断右子树走过没,如果打印过F了,就记录下来。
void PostOrderNor(pBTNode pRoot)
{
if (pRoot) {
Stack s;
init(&s);
pBTNode pCur = pRoot;
pBTNode pPre = NULL;
pBTNode pTop = NULL;
while (!isEmpty(&s) || pCur) {
while (pCur) {
pushBack(&s, pCur);
pCur = pCur->_pLeft;
}
pTop = top(&s);
//判断如果栈顶结点有右结点且没走过,遍历右子树
if (pTop->_pRight && pPre != pTop->_pRight) {
pCur = pTop->_pRight;
}
else {
//左右子树都遍历过了,打印根节点
pPre = pTop;
printf("%c ", pTop->_data);
pop(&s);
//pCur = top(&s)->_pRight;右子树退回来死循环
}
}
}
}
判断是否完全二叉树——层序
找到第一个不饱和结点(无右,或者无左无右),找到后置标志,队列中其后结点不能有子节点。
int IsComTree(pBTNode pRoot)
{
LQueue q;
InitQueue(&q);
PushQueue(&q, pRoot);
int flag = 0;
while (!QueueEmpyt(&q)) {
pBTNode pCur = QueueFront(&q);
PopQueue(&q);
if (flag == 1) {
if (pCur->_pLeft || pCur->_pRight) {
return 0;
}
}
if (pCur->_pLeft && pCur->_pRight) {
//正常的双子结点
PushQueue(&q, pCur->_pLeft);
PushQueue(&q, pCur->_pRight);
}
else if (pCur->_pLeft) {
//第一个不饱和结点
flag = 1;
PushQueue(&q, pCur->_pLeft);
}
else if ((NULL == pCur->_pLeft && NULL == pCur->_pRight)) {
//也不饱和,但子节点不入队列
flag = 1;
}
else if(pCur->_pRight){
//没有左子树,有右子数
return 0;
}
}
return 1;
}
判断结点是否在树里
1.传值
扫描二维码关注公众号,回复:
561027 查看本文章
pBTNode IsDataInTree(pBTNode pRoot, BTDataType data)
{
if (pRoot) {
if (pRoot->_data == data) {
return pRoot;
}
pBTNode pRet = NULL;
if (pRet = IsDataInTree(pRoot->_pLeft, data)) {
return pRet;
}
if (pRet = IsDataInTree(pRoot->_pRight, data)) {
return pRet;
}
}
return NULL;
}
2.传值
int IsNodeInTree(pBTNode pRoot, pBTNode node)
{
if (pRoot) {
if (pRoot == node) {
return 1;
}
if (IsNodeInTree(pRoot->_pLeft, node)) {
return 1;
}
if (IsNodeInTree(pRoot->_pRight, node)) {
return 1;
}
}
return 0;
}