桂电七院数据结构实验报告四

源代码的调试

在DEVC++中初步运行会报一堆错,而且有好多代码都被打进了注释,修改之后如下

#include<stdio.h>
#include<stdlib.h>
#define M 100
#define Null 0
typedef struct node { /*二叉链表结点结构*/
	int data;  /*数据域*/
	struct node *lchild,*rchild;/*左、右孩子域*/
} bitree;

bitree *que[M]; /*定义一个指针数组,说明队列中的元素类型为bitree指针类型*/
int front=0,rear=0; /*初始化循环队列*/

bitree *creat() { /*建立二叉树的递归算法*/
	bitree *t;
	int x;
	scanf("%d",&x);
	if(x==0) t=Null; /*以x=0表示输入结束*/
	else {
		t=(bitree *)malloc(sizeof(bitree));/*动态生成结点t,分别给结点t的数据域、左右孩子域赋值,给左右孩子域赋值时用到了递归的思想。*/
		t->data=x;
		t->lchild=creat();
		t->rchild=creat();
	}
	return t;
}

void inorder(bitree *t) { /*中序遍历二叉树的递归算法*/
	if(t!=Null) {
		inorder(t->lchild);
		printf("%4d",t->data);
		inorder(t->rchild);
	}
}

void enqueue(bitree *t) { /*把bitree类型的结点*t入队列*/
	if(front!=(rear+1)%M) { /*判断队列是否已满*/
		rear=(rear+1)%M;
		que[rear]=t;
	}
}

bitree *delqueue() {
	if(front==rear) /*判断队列不为空*/
		return Null;
	front=(front+1)%M;
	return (que[front]);

}

void levorder(bitree *t) {/*层次遍历二叉树的算法*/
	bitree *p;
	if(t!=Null) {
		enqueue(t); /*根结点入队*/
		while(front!=rear) { /*当当前队列不为空时*/
			p=delqueue(); /*输出对头元素,并把其左右孩子入队。此过程一直递归,直到队列为空*/
			printf("%4d",p->data);
			if(p->lchild!=Null)
				enqueue(p->lchild);
			if(p->rchild!=Null)
				enqueue(p->rchild);
		}
	}
}
main() { /*主函数*/
	bitree *root;
	printf("\n");
	root=creat();
	inorder(root);
	printf("\n");
	levorder(root);
}

(1) 写出二叉树前序遍历和后序遍历的递归算法,并在主函数中调用它,调试好程序并分析其运行结果。

前后序遍历在书上有写

#include<stdio.h>
#include<stdlib.h>
#define M 100
#define Null 0
typedef struct node { /*二叉链表结点结构*/
	int data;  /*数据域*/
	struct node *lchild,*rchild;/*左、右孩子域*/
} bitree;

bitree *que[M]; /*定义一个指针数组,说明队列中的元素类型为bitree指针类型*/
int front=0,rear=0; /*初始化循环队列*/

bitree *creat() { /*建立二叉树的递归算法*/
	bitree *t;
	int x;
	scanf("%d",&x);
	if(x==0) t=Null; /*以x=0表示输入结束*/
	else {
		t=(bitree *)malloc(sizeof(bitree));/*动态生成结点t,分别给结点t的数据域、左右孩子域赋值,给左右孩子域赋值时用到了递归的思想。*/
		t->data=x;
		t->lchild=creat();
		t->rchild=creat();
	}
	return t;
}

void preorder(bitree *t) {//前 
	if(t!=NULL) {
		printf("%   4d",t->data);
		preorder(t->lchild);
		preorder(t->rchild);
	}
}

void inorder(bitree *t) { /*中序遍历二叉树的递归算法*/
	if(t!=Null) {
		inorder(t->lchild);
		printf("%4d",t->data);
		inorder(t->rchild);
	}
}

void postorder(bitree *t) {//后 
	if(t!=NULL) {
		postorder(t->lchild);
		postorder(t->rchild);
		printf("%4d",t->data);

	}
}

void enqueue(bitree *t) { /*把bitree类型的结点*t入队列*/
	if(front!=(rear+1)%M) { /*判断队列是否已满*/
		rear=(rear+1)%M;
		que[rear]=t;
	}
}

bitree *delqueue() {
	if(front==rear) /*判断队列不为空*/
		return Null;
	front=(front+1)%M;
	return (que[front]);

}

void levorder(bitree *t) {/*层次遍历二叉树的算法*/
	bitree *p;
	if(t!=Null) {
		enqueue(t); /*根结点入队*/
		while(front!=rear) { /*当当前队列不为空时*/
			p=delqueue(); /*输出对头元素,并把其左右孩子入队。此过程一直递归,直到队列为空*/
			printf("%4d",p->data);
			if(p->lchild!=Null)
				enqueue(p->lchild);
			if(p->rchild!=Null)
				enqueue(p->rchild);
		}
	}
}
main() { /*主函数*/
	bitree *root;
	printf("\n");
	root=creat();
	printf("前\n");
	preorder(root);
	printf("\n中\n");
	inorder(root);
	printf("\n后\n");
	postorder(root);
	printf("\n层次\n");
	levorder(root);
}

(2) 在二叉树的层次遍历中,如果不采用循环队列,而是采用顺序队列,会出现什么问题?

会出现假溢现象

(3) 写出二叉树三种遍历的非递归算法,并在主函数中调用它,调试好程序并分析其运行结构。

这里后序的非递归算法比较难写,需要多想
先序遍历是根-左-右
先遍历左孩子,再将它输出出来。当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,右孩子直至孩子全部遍历结束
中序遍历是左-根-右
先把所有左孩子入栈,左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子,右孩子入栈
后序遍历是左-右-根
对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时仍不能将其出栈,因为它的右孩子还没有被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。

#include<stdio.h>
#include <stdlib.h>
#define M 100
typedef struct node {
	int data;
	int cishu;
	struct node *lchild;
	struct node *rchild;  //树节点中cishu是为了计数用。在后序遍历中,子树的根节点在第一次遍历的时候不会输出,只有在第二次遍历的时候才输出。
} bitree;


typedef struct stack {
	bitree *elements[M];
	int top;
} seqstack; //定义一个储存树类型地址的栈,方便遍历的时候追踪到树的地址。

bitree *root;//定义一个树根
seqstack s;//定义栈

void setnull() { //初始化栈
	s.top =0;
}

void push(bitree *temp) { //入栈操作
	s.elements[s.top++] = temp;
}

bitree *pop() { //取栈顶并出栈顶
	return s.elements[--s.top];
}

int empty() { //判断空栈
	return s.top == 0;
}

bitree *creat() { /*建立二叉树的递归算法*/
	bitree *t;
	int x;
	scanf("%d",&x);
	if(x==0) t=NULL; /*以x=0表示输入结束*/
	else {
		t=(bitree*)malloc(sizeof(bitree));//动态生成结点t,分别给结点t的数据域、左右孩子域
		t->data=x;                  //赋值,给左右孩子域赋值时用到了递归的思想。
		t->lchild=creat();
		t->rchild=creat();
	}
	return t;
}

void preorder(bitree *t) { //前序遍历的非递归算法
	bitree *temp = t;//定义一个树节点,用它来遍历
	while(temp != NULL || s.top != 0) {
		while(temp != NULL) { //先遍历左孩子,并输出。
			printf("%4d",temp->data);
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0) { //当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,直至孩子全部遍历结束。
			temp = pop();
			temp = temp->rchild;
		}
	}
	printf("\n");
}

void inorder(bitree *t) { //中序遍历的非递归算法
	bitree *temp = t;
	while(temp != NULL||s.top != 0) {
		while(temp != NULL) { //先把左孩子入栈,所有左孩子入栈结束
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0) { //左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子
			temp = pop();
			printf("%4d",temp->data);
			temp = temp->rchild;
		}
	}
	printf("\n");
}


void laorder(bitree *root) { //后序遍历的非递归算法
	bitree *temp = root;
	while(temp!=NULL||s.top!=0) {
		while(temp!= NULL) {
			temp->cishu=1;       // 当前节点首次被访问
			push(temp);
			temp=temp->lchild;
		}
		if(s.top!=0) {
			temp=pop( );
			if(temp->cishu == 1) { // 第一次出现在栈顶

				temp->cishu++;
				push(temp);
				temp=temp->rchild;
			} else if(temp->cishu==2) { //第二次输出并制空,防止陷入死循环
				printf("%4d",temp->data);
				temp=NULL;
			}
		}
	}
	printf("\n");
}


int main() {
	bitree *root;//创建根
	setnull();//制空栈
	root=creat();//创建二叉树:尝试输入:1 2 3 0 0 4 0 0 5 6 0 0 7 0 0
	printf("前序遍历:\n");
	preorder(root);
	printf("中序遍历:\n");
	inorder(root);
	printf("后序遍历:\n");
	laorder(root);
	return 0;
}

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值