18黑马笔记之二叉树的非递归遍历

18黑马笔记之二叉树的非递归遍历

1 直接用例子说明:
在这里插入图片描述
节点格式:

typedef struct BINTREESTACKNODE{
	LinkSNode node;  //挂钩
	BinaryNode *root; //二叉树节点
	bool flag;   //出入栈时是否可输出的标志位
}BinTreeStackNode;

首先,将节点A进栈(初始化为false)。然后取栈顶元素,判断flag是否为真,为真就输出并释放内存。不为真就放其左右节点进栈,A改为true再放进栈中。再取栈顶元素判断,如此循环便可遍历整个二叉树。

2 代码实现:

1)头文件.h

#ifndef SEQLINKSTACK
#define SEQLINKSTACK

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//使用企业链表实现,也可传统
typedef struct LINKSNODE{
	struct LINKSNODE *next;
}LinkSNode;

//管理链表结构体
typedef struct LINKSTACK{
	LinkSNode head;
	int size;
}LinkStack;

//链式栈初始化
LinkStack* Init_LinkStack();
//入栈
int Push_LinkStack(LinkStack *lstack,LinkSNode *data);
//出栈
int Pop_LinkStack(LinkStack *lstack);
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack);
//返回第一个有效元素
LinkSNode *Top_LinkStack(LinkStack *lstack);
//返回栈大小
int Size_LinkStack(LinkStack *lstack);
//清空链式栈
int Clear_LinkStack(LinkStack *lstack);
//释放内存
int Destory_LinkStack(LinkStack *lstack);

#endif

2)cpp文件:

#include"Seq_LinkStack.h"

//链式栈初始化 ok
LinkStack* Init_LinkStack(){

	LinkStack *lstack=(LinkStack*)malloc(sizeof(LinkStack));
	lstack->head.next=NULL;    
	lstack->size=0;

	return lstack;
}
//入栈 ok
int Push_LinkStack(LinkStack *lstack,LinkSNode *data){

	if(lstack==NULL){
		return -1;
	}
	if(data==NULL){
		return -1;
	}
	//每次都在链表的头结点插入,与顺序栈想反
	//所以每次对头结点操作插入
	data->next =lstack->head.next;
	lstack->head.next=data;

	lstack->size++;

	return 0;
}
//出栈  ok
int Pop_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return -1;
	}
	if(lstack->size==0){
		return -1;
	}
	//也是只对头结点操作
	//使头结点指向第二个有效节点
	LinkSNode *first=lstack->head.next;
	lstack->head.next=first->next;  //使head指向第二个元素

	lstack->size--;

	return 0;

}
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	if(lstack->size==0){
		return 1;
	}
	
	return 0;
}
//返回第一个有效元素 ok
LinkSNode *Top_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return NULL;
	}
	if(lstack->size==0){
		return NULL;
	}
	return lstack->head.next;

}
//返回栈大小  ok
int Size_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return -1;
	}

	return lstack->size;
}
//清空链式栈 ok
int Clear_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	//lstack->head.next=NULL;
	lstack->size=0;

	return 0;
}
//释放内存
int Destory_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	free(lstack);

	return 0;
}

3)具体逻辑代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"Seq_LinkStack.h"

//定义二叉树节点
typedef struct BINARYNODE{
	char ch;
	struct BINARYNODE *lchild;  
	struct BINARYNODE *rchild;  
}BinaryNode;

//利用链式栈进行非递归遍历
//栈的节点
typedef struct BINTREESTACKNODE{
	LinkSNode node;  //挂钩
	BinaryNode *root; //二叉树节点
	bool flag;   //出入栈时是否可输出的标志位
}BinTreeStackNode;



//二叉树的递归遍历 ok 懂了
void Recursion(BinaryNode *root){

	if(root==NULL){
		return ;
	}
	//前序遍历 --根左右
	printf("%c",root->ch);
	Recursion(root->lchild);
	Recursion(root->rchild);

	return ;
}


//创建栈节点,将二叉树放进栈中
BinTreeStackNode *MyStackNode(BinaryNode *root,bool flag){
	BinTreeStackNode *node=(BinTreeStackNode*)malloc(sizeof(BinTreeStackNode));
	node->root=root;
	node->flag=false;

	return node;
}

//二叉树的非递归遍历
int UnRecursion(BinaryNode *root){

	//创建栈
	LinkStack *stack=Init_LinkStack();

	//先创建一个二叉树节点放进栈中
	Push_LinkStack(stack,(LinkSNode*)MyStackNode(root,false));   //必须是放带有二叉树节点的节点进去


	//循环放与弹出
	while(Size_LinkStack(stack)>0){

		//先取出栈中元素
		BinTreeStackNode *pcur=(BinTreeStackNode*)Top_LinkStack(stack);
		Pop_LinkStack(stack);    

		//若二叉树节点为空则不作处理 即不处理节点的空孩子(为空嘛)
		if(pcur->root==NULL){
			continue;
		}
		//若为真则显示并释放节点内存
		if(pcur->flag==true){
			printf("%c",pcur->root->ch);
			free(pcur);
		}else{
			//否则就将它左右子树和本身放进栈中,并且本身变为true
			//前序,但因为栈是先进后出所以倒转
			Push_LinkStack(stack,(LinkSNode*)MyStackNode(pcur->root->rchild,false));
			Push_LinkStack(stack,(LinkSNode*)MyStackNode(pcur->root->lchild,false));
			pcur->flag=true;
			Push_LinkStack(stack,(LinkSNode*)pcur);
			//这四句改一下就是中序,后序
		}


	}

	printf("\n");

	return 0;
}

void CreateBinartTree(){

	//创建数据节点
	BinaryNode node1={'A',NULL,NULL};
	BinaryNode node2={'B',NULL,NULL};
	BinaryNode node3={'C',NULL,NULL};
	BinaryNode node4={'D',NULL,NULL};
	BinaryNode node5={'E',NULL,NULL};
	BinaryNode node6={'F',NULL,NULL};
	BinaryNode node7={'G',NULL,NULL};
	BinaryNode node8={'H',NULL,NULL};

	//建立节点关系 A-F-G-H
	//              \B
	//               \C-E
	//                \D
	node1.lchild=&node2;
	node1.rchild=&node6;
	node2.rchild=&node3;
	node3.lchild=&node4;
	node3.rchild=&node5;
	node6.rchild=&node7;
	node7.rchild=&node8;

	//非递归遍历
	UnRecursion(&node1);

	//递归遍历
	Recursion(&node1);
	printf("\n");
}

int main(){

	CreateBinartTree();

	return 0;
}


//总结:这个项目有问题再释放内存那里,但是我分析过了代码应该没有问题才对啊!!!
//懂了,在拷贝时出问题!不能用原来的树的内容给他指向,导致两个二叉树的两个指针指向同一片区域,
//必须新建变量给他新的指向

//总结:名字起得有点长,自己都记不住!!!

总结二叉树的非递归遍历:与栈的应用之就近匹配思想基本一样。即第08编文章。

发布了54 篇原创文章 · 获赞 1 · 访问量 698

猜你喜欢

转载自blog.csdn.net/weixin_44517656/article/details/105602295