【算法学习笔记】09.数据结构基础 二叉树初步练习2

此次重点在于 二叉树的结构体构造(指针的大量练习),数组方式构造(简易)

建树的输入方式为,

(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) () 

()表示结束LL表示从根节点开始向右移两次,并且同时延伸 (5,)表示根节点

首先还是先来比较麻烦的结构体构造方法,但是看起来很高端。

char s[100];//保存输入 
int Failed=0,cnt=0; //表明是否输入有误 cnt是计数器 记录节点数目
//定义结构体
typedef struct Tnode //自定义一个结构体
{
	int hv;// have been valued
	int v;//存储节点数值
	struct Tnode *l,*r;//左右儿子 都是指向Tnode的指针 此时不能用Node*是因为Node还没有定义完全
} Node;//命名在Node 
//发现了 二叉树的定义过程中其实用到了递归的方法
Node* root;//此为根节点 

//此函数用来创建新node且为之申请动态内存 stdlib.h
Node* newnode() 
{
	Node* u = (Node*)malloc(sizeof(Node)) ;//将申请来的内存格式化
	if(u != NULL)//防止是非法内存
	{
		u->hv=0;//为u初始化
		u->l=u->r=NULL;//还无左右儿子 连续赋值 必须赋值为空 否则后续无法判断是否为空
	}
	return u;//返回新建的节点
}   
//向已有的树上添加节点 v来赋值 s来确定节点位置
void addnode(int v,char *s)
{
	//按照移动序列行走 *s =="LL)"
	int len=strlen(s);//用来做循环控制
	Node* u =root;//起点是root根节点 每一次寻找位置都要从根节点开始
	for(int i=0;i<len;i++)
	{
		if(s[i]=='L')
		{
			if(u->l==NULL) u->l=newnode();//找到了空节点,说明要进行延伸
			u=u->l;//向左走 //延伸了之后才能移动
		}else if(s[i]=='R')
		{
			if(u->r==NULL) u->r=newnode();
			u=u->r;//向左走 	
		}
	}
<span style="white-space:pre">	</span>//此时已经找到了要赋值的节点了
	if(u->hv) Failed=1;//如果输入有误则报错
	else
	{
		u->v=v;
		u->hv=1;
	} 
}
//读入并建树
int read()
{
	Failed=0;//每次新建树时要重置
	remove_tree(root) ;//释放原有内存 
	root = newnode();//为根节点进行初始化 ,建立一棵新树 主要是为了覆盖上一次的树 
	for(;;)//不断地读入
	{
		if(scanf("%s",s)!=1)	
			return 0;//表示输入结束 
		//strcmp 的返回值比较奇葩 若str1=str2,则返回零 说明完全相同
		if(!strcmp(s,"()")) break;//如果读入的是()就表示完成了一次输入 return 1
		int v;//存储节点值
		sscanf(&s[1],"%d",&v);//&s[1] 返回的是从s的第二个字符到结尾\0的数组 sscanf 从字符数组中读入v
		addnode(v,strchr(s,',')+1);//strchr(s,',')返回的正好是','的指针,再+1 
	}	 
	return 1; 
}
void remove_tree(Node* u)
{
	if(u==NULL)
		return;//走到某一个叶子时就return 
	//利用递归循环删除 
	remove_tree(u->l);
	remove_tree(u->r);
	free(u);
	
}


此种方法的优点是比较易懂,后序过程时思考难度下降,并且是动态内存,所以不用管数据的大小

还有一种避免指针的方式,就是用数组来进行建树。

const int root=1; int left[10000],right[10000],cnt; int nodes[10000]={0};
//left和right只用来记录节点之间的父子关系,且序号是按照输入顺序进行的
//真正的数据值存储在nodes里
bool failed = false; char s[100];
//建立一棵新树,
void newtree()
{
	left[root]=right[root]=0;
	cnt=1;
	memset(nodes,0,sizeof(nodes));
} 
int newnode()
{
<span style="white-space:pre">	</span>int u = ++cnt;//使cnt增加1  表明有了一个新的节点 
<span style="white-space:pre">	</span>left[u]=right[u]=0;
<span style="white-space:pre">	</span>return u;//返回u 
}


void addnode(int v,char *s)//值v s= LL) 
{
<span style="white-space:pre">	</span>int len= strlen(s);
<span style="white-space:pre">	</span>int t=root;
<span style="white-space:pre">	</span>for(int i=0;i<len;i++) 
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>//先找到节点位置,如果遇到空就建立新节点 
<span style="white-space:pre">		</span>if(s[i]=='L')
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if(left[t]==0)
<span style="white-space:pre">				</span>left[t]=newnode();//如果当前的左边是空的就建立一个节点
<span style="white-space:pre">			</span>t=left[t];//向左走  
<span style="white-space:pre">		</span>}else
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if(s[i]=='R')
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>if(right[t]==0)
<span style="white-space:pre">					</span>right[t]=newnode();//如果当前的左边是空的就建立一个节点
<span style="white-space:pre">				</span>t=right[t];//向左走  
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>} 
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>if(nodes[t])
<span style="white-space:pre">		</span>failed = true;
<span style="white-space:pre">	</span>else
<span style="white-space:pre">		</span>nodes[t]=v;
<span style="white-space:pre">		</span> 
}   
int read()
{
<span style="white-space:pre">	</span>newtree();
<span style="white-space:pre">	</span>while(scanf("%s",s)==1)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if(!strcmp(s,"()")) 
<span style="white-space:pre">			</span>return 1;//结束 
<span style="white-space:pre">		</span>int d=0;
<span style="white-space:pre">		</span>sscanf(&s[1],"%d",&d);
<span style="white-space:pre">		</span>addnode(d,strchr(s,',')+1);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return 0;
}  

 代码其实并没有减少多少,说简单了但是其实也有点复杂 比如left right nodes 三个数组之间的关系有时候会闹不清楚 
 

转载于:https://www.cnblogs.com/yuchenlin/p/4379265.html

#include #include //#define error 0 //#define OVERFLOW -1 //#define ok 1 #define MAXSIZE 100 typedef char TElemType; typedef int Status; typedef struct BiTNode{ //树的结点 TElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; typedef BiTree datatype; typedef struct { datatype data[MAXSIZE]; int top; }sqstack; typedef sqstack *STK; Status CreateBiTree(BiTree *T) { //先序建立二叉树 char ch; ch=getchar(); if(ch=='#') (*T)=NULL; //#代表空 else { (*T)=(BiTree)malloc(sizeof(BiTNode)); (*T)->data=ch; CreateBiTree(&(*T)->lchild); //先序建立左子树 CreateBiTree(&(*T)->rchild); //先序建立右子树 } return 1; } STK initstack() //栈的初始化 { STK s; s=(STK)malloc(MAXSIZE*sizeof(sqstack)); s->top=0; return s; //返回指向栈地址的指针 } Status stackempty(STK s) //判断栈是否为空 { return(s->top==0); } Status push(STK s,datatype *e) //压栈函数 { if(s->top==MAXSIZE) //栈满,则返回错误 return 0; else { s->data[s->top]=*e; (s->top)++; return 1; } } Status pop(STK s,datatype *e) //出栈函数 { if(stackempty(s)) //判断栈是否为空 return 0; else { s->top--; *e=s->data[s->top]; //用e接受栈顶元素 return 1; } } Status inordertraverse(BiTree T) //中序非递归遍历二叉树 { STK s; s=initstack(); // BiTree T; BiTree p; p=T; while (p||!stackempty(s)) { if(p) { push(s,&p); p=p->lchild; } else { pop(s,&p); printf("%2c",p->data); p=p->rchild; }//else }//while return 1; }//inordertraverse void main() { BiTree T=NULL; printf("\n Creat a Binary Tree .\n"); //建立一棵二叉树T* CreateBiTree( &T ); printf ("\nThe preorder is:\n"); inordertraverse(T); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值