#include <iostream>
#include <cstdio>
#include <malloc.h>
using namespace std;
/*
* 前序遍历栈的实现逻辑
* 根 左 右 节点入栈并且输出 入到叶子节点 出栈 父节点遍历右子树
* */
struct treeNode {
int a; // 数据成员
struct treeNode *pFather; // 父节点
struct treeNode *pLeft; // 左孩子
struct treeNode *pRight; // 右孩子
};
// 链表结构的栈 尾添加尾删除 双向带空头链表
// 栈节点
struct stack {
struct treeNode *node; // 指向树的节点
struct stack *pre; // 指向前一个节点
struct stack *next; // 指向下一个节点
};
struct stack head; // 空头
struct stack *stacktop = &head; // 栈顶指针
// 入栈 链表尾添加
void push(struct treeNode *node) {
// 申请节点 并且成员赋值
struct stack *temp = (struct stack *)malloc(sizeof(struct stack));
if (NULL == temp) {
return ;
}
// 赋初值
temp->pre = NULL;
temp->next = NULL;
temp->node = node;
// 尾巴连接
stacktop->next = temp;
temp->pre = stacktop;
// 栈顶指针后移
stacktop = stacktop->next;
}
// 出栈 双向链表尾删除
struct treeNode *pop(void) {
if (stacktop == &head) {
// 栈空
return NULL;
}
struct treeNode *temp = stacktop->node; // 得到栈顶的树节点
stacktop = stacktop->pre; // 节点前移
free(stacktop->next); // 释放节点
stacktop->next = NULL; // 新尾指针指向空
return temp;
}
// 中序遍历 递归写法
// 递归遍历时 递归数量有限制 栈默认大小是1M 大概几百个节点就满了
void cen_look(struct treeNode *root) {
if (root != NULL) {
cen_look(root->pLeft);
printf("%d ", root->a);
cen_look(root->pRight);
}
}
// 中序遍历 栈写法
// 与前序遍历的区别是 前序遍历是入一个输出一个 而中序遍历是出栈的时候输出
void cenLookByStack(struct treeNode *root) {
if (NULL == root)
return ;
struct treeNode *tp = root;
// 死循环 里面break
while (NULL != tp || stacktop != &head) {
// 左子树入栈并输出 一直到叶子
while (tp != NULL) {
// printf("%d ", tp->a);
push(tp);
tp = tp->pLeft;
}
struct treeNode *t = pop(); // 出栈
printf("%d ", t->a); // 出栈后输出
tp = t->pRight;
// if (NULL == tp && stacktop == &head) // 栈为空并且最后一个节点没有孩子
// break;
}
}
int main() {
struct treeNode t1 = { 1 };
struct treeNode t2 = { 2 };
struct treeNode t3 = { 3 };
struct treeNode t4 = { 4 };
struct treeNode t5 = { 5 };
struct treeNode t6 = { 6 };
struct treeNode t7 = { 7 };
struct treeNode t8 = { 8 };
struct treeNode t9 = { 9 };
struct treeNode t10 = { 10 };
// 链接
t1.pLeft = &t2;
t1.pRight = &t3;
t1.pFather = NULL;
t2.pLeft = &t4;
t2.pRight = &t5;
t2.pFather = &t1;
t3.pRight = &t6;
t3.pLeft = NULL;
t3.pFather = &t1;
t4.pLeft = NULL;
t4.pRight = NULL;
t4.pFather = &t2;
t5.pLeft = &t7;
t5.pRight = &t8;
t5.pFather = &t2;
t6.pLeft = &t9;
t6.pRight = &t10;
t6.pFather = &t3;
t7.pLeft = NULL;
t7.pRight = NULL;
t7.pFather = &t5;
t8.pLeft = NULL;
t8.pRight = NULL;
t8.pFather = &t5;
t9.pLeft = NULL;
t9.pRight = NULL;
t9.pFather = &t6;
t10.pLeft = NULL;
t10.pRight = NULL;
t10.pFather = &t6;
printf("递归中序遍历:\n");
cen_look(&t1);
printf("\n栈写法中序遍历(双向带空头链表):\n");
cenLookByStack(&t1);
return 0;
}