数据结构06树和森林

数据结构之树和森林

提示:数据结构中树,森林的创建和二叉树的创建有着相似之处,都可以利用二叉树相关性质进行创建。
所以在本文章中我会重点对二叉树与树之间的差异点和共同点进行对比讲解,希望能给正在学习树的同学有一点帮助。



一.树的基础知识点的讲解

树的基础知识点(在这里只介绍常见的孩子兄弟表示法)

在这里插入图片描述
观察发现
任意发现,任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针
分别指向该结点的第一个孩子和此节点的右兄弟。
及创建树的节点的结构为

typedef struct bintreenode
{
elemtype data;
bintreenode *firstchild,*nextsibling;
}bintreenode,*binlink;

这样可以树的结构转化为二叉树结构
在这里插入图片描述
因为在书中没有左右子树的概念,只有先根遍历和后根遍历的概念,与转化的二叉树的先序遍历和中序遍历相对应。


提示:以下是本篇文章正文内容,下面案例可供参考(本次代码实现中节点的data值的类型为字符串,所以在上篇文章的createbyedge中细节处做了改动)

二、代码实现

step1.头文件的引入

queue.h引入

#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<string.h>

struct bintreenode;

#define qelemtype bintreenode*

typedef struct qnode
{
	qelemtype data;
	struct qnode *next;
}qnode,*qlink;

typedef struct
{
  qlink front;
  qlink rear;
}linkqueue;

void initqueue(linkqueue &q);
int isempty(linkqueue q);
void pushqueue(linkqueue &q,qelemtype e);
void popqueue(linkqueue &q,qelemtype &e);

void initqueue(linkqueue &q)
{
	q.front=q.rear=(qlink)malloc(sizeof(qnode));
    q.front->next=NULL;
}
void pushqueue(linkqueue &q,qelemtype e)
{
	qlink p;
    p=(qlink)malloc(sizeof(qnode));
	p->data=e;
	p->next=NULL;
	q.rear->next=p;
	q.rear=p;
}
void popqueue(linkqueue &q,qelemtype &e)
{
	if(q.front==q.rear)
	{
       printf("队为空,没有可以删除的");
	}
	else
	{
		qlink p=q.front->next;
		e=p->data;
		q.front->next=p->next;
		if(q.rear==p)
			q.rear=q.front;
		free(p);
	}
}

int isempty(linkqueue q)
{
   if(q.front==q.rear)
	   return 1;
   else
	   return 0;
}

stack.h引入

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

#define elemtype char

typedef struct bintreenode
{
	elemtype data;
    bintreenode *firstchild,*nextsibling;
}bintreenode,*binlink;

#define Elemtype bintreenode*

typedef struct snode {
	Elemtype data;
	struct snode* next;
}snode, * linkstack;

typedef struct snode_ {
	Elemtype data;
	struct snode_* next;
}snode_, * linkstack_;

void initstack(linkstack& s);
void pushstack(linkstack& s, Elemtype x);
void popstack(linkstack& s, Elemtype& x);
void pushstack_(linkstack_& s, Elemtype x);
void popstack_(linkstack_& s, Elemtype& x);
void printfstack(linkstack s);
int isempty(linkstack &s);


void initstack(linkstack& s)
{
	s = (linkstack)malloc(sizeof(snode));
	s->next = NULL;
	//s = NULL;
}

void pushstack(linkstack& s, Elemtype x)
{
	linkstack p = (linkstack)malloc(sizeof(snode));
	p->data = x;
	p->next = s;
	s = p;
}
void pushstack_(linkstack_& s, Elemtype x)
{
	linkstack_ p = (linkstack_)malloc(sizeof(snode_));
	p->data = x;
	p->next = s;
	s = p;
}
void popstack(linkstack& s, Elemtype& x)
{
	linkstack p = s;
	x = p->data;
	if(s->next==NULL)
	{
		s->next = NULL;
	}
	else {
		s = s->next;
	}
	free(p);
}
void popstack_(linkstack_& s, Elemtype& x)
{
	linkstack_ p = s;
	x = p->data;
	if (s->next == NULL)
	{
		s->next = NULL;
	}
	else {
		s = s->next;
	}
	free(p);
}

int isempty(linkstack &s)
{
   if(s->next==NULL)
   {
	   return 1;
   }
   else
   {
	   return 0;
   }
}
void printfstack(linkstack s)
{
	if(s->next!=NULL)
	{
		printfstack(s->next);
		binlink bt=s->data;
		printf("%c",bt->data);
	}
}

step2.创建树结构

way1.先序字符串

void createbystr(forest *bt)
{
  createbystr(bt->root);
}
void createbystr(binlink &t)
{
	elemtype str[30];
	scanf("%s",str);
	initnode(t);
	if(strcmp(str,"#")==0)
	{
		t=NULL;
	}
	else
	{
		strcpy(t->data,str);
		createbystr(t->firstchild);
		createbystr(t->nextsibling);
	}
	
}

way2.边输边创建

void createbyedge(forest *bt)
{
  createbyedge(bt->root);
}
void createbyedge(binlink &t)
{
	initnode(t);
	char f[30],s[30];
	scanf("%s%s",f,s);
	linkqueue q;
	initqueue(q);
	binlink bt,bc,bs;
	initnode(bs);
	if(strcmp(f,"#")==0)
	{
		strcpy(t->data,s);
	    pushqueue(q,t);
	}
	getchar();
	scanf("%s%s",f,s);
while(!isempty(q))
{
	popqueue(q,bt);
	if(strcmp(bt->data,f)==0)
	{
		initnode(bc);
		strcpy(bc->data,s);
		bt->firstchild=bc;
		pushqueue(q,bc);
		getchar();
	    scanf("%s%s",f,s);
		if(strcmp(s,"#")==0)
			return;
		while(strcmp(bt->data,f)==0)
		{
			strcpy(bs->data,s);
			bc->nextsibling=bs;
			pushqueue(q,bs);
			getchar();
	        scanf("%s%s",f,s);
	    	bc=bs;
			initnode(bs);
		}
		
	}
}
}

step3.相应功能的实现

1.查找指定名称的节点

binlink find(forest *bt,elemtype *str)
{
   return find(bt->root,str);
}
binlink find(binlink &t,elemtype *str)
{
	if(t)
	{
		if(strcmp(t->data,str)==0)
			return t;
		binlink p=find(t->firstchild,str);
		if(p)
			return p;
		else
			return find(t->nextsibling,str);
	}
	else
		return NULL;
}

2.查找指定名称的父节点

binlink findfather(forest *bt,elemtype *str)
{
	binlink p=find(bt->root,str);
	 return  findfather(bt->root,p);
}
binlink findfather(binlink &t,binlink p)
{
   if(t==NULL||p==NULL||p==t)
	   return NULL;
   binlink q=t->firstchild;
   binlink parent;
   while(q&&q!=p)
   {
     parent=findfather(q,p);
	 if(parent)
		 return parent;
	 q=q->nextsibling;
   }
   if(q==p)
	   return t;
   return NULL;
}

3.输出所有叶子节点的路径

void output(forest *bt)
{
	output(bt->root);
}
void output(binlink &t)
{
	linkstack s;
	initstack(s);
	while(t)
	{
		pushstack(s,t);
		t=t->firstchild;
		if(!t)
		{
			printfstack(s);
			popstack(s,t);
			if(t->nextsibling)
		    	t=t->nextsibling;
			else
			{
				do
				{
					popstack(s,t);
				}while(!t->nextsibling);
				t=t->nextsibling;
			}
		}
	}
}

4.删除指定名称的节点

void deletenode(forest *bt,elemtype *str)
{
	binlink fnode=findfather(bt,str);
	binlink cnode=find(bt,str);
	deletenode(fnode,cnode);
}
void deletenode(binlink &fnode,binlink &cnode)
{
   if(fnode->firstchild==cnode)
   {
	   fnode->firstchild=NULL;
	   destroynode(cnode);
   }
   else
   {
     binlink bt=fnode->firstchild;
	 while(bt->nextsibling!=cnode)
		 bt=bt->nextsibling;
     bt->nextsibling=NULL;
	 destroynode(cnode);

   }
}

5.插入指定父节点的节点

void insert(forest *bt,elemtype *str1,elemtype *str2)
{
	binlink fnode=find(bt->root,str1);
    insert(fnode,str2);
}
void insert(binlink &fnode,elemtype *str)
{
	binlink cnode,bt;
	initnode(cnode);
	strcpy(cnode->data,str);
	if(!fnode->firstchild)
	{
		fnode->firstchild=cnode;	
	}
	else
	{
		bt=fnode->firstchild;
		while(bt->nextsibling)
			bt=bt->nextsibling;
		bt->nextsibling=cnode;
	}
}

6.先序遍历树

void preorder(forest*bt)
{
	preorder(bt->root);
}
void preorder(binlink &t)
{
    if(t)
	{
		printf("%s",t->data);
		printf("  ");
		preorder(t->firstchild);
		preorder(t->nextsibling);
	}
}

树的应用赫尔曼编码我会放在下一个文章中单独写
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值