实验五 二叉树基本操作的编程实现
【实验目的】
内容:二叉树基本操作的编程实现
要求:
二叉树基本操作的编程实现(2学时,验证型),掌握二叉树的建立、遍历、插入、删除等基本操作的编程实现,也可以进一步编程实现查找等操作,存储结构主要采用顺序或链接结构。也鼓励学生利用基本操作进行一些应用的程序设计。
【实验性质】
验证性实验(学时数:2H)
【实验内容】
以下的选题都可以作为本次实验的推荐题目
- 建立二叉树,并以前序遍历的方式将结点内容输出。
- 将一个表示二叉树的数组结构转换成链表结构。
- 将表达式二叉树方式存入数组,以递归方式建立表达式之二叉树状结构,再分别输出前序、中序及后序遍历结果,并计算出表达式之结果。
【注意事项】
1.开发语言:使用C。
2.可以自己增加其他功能。
【实验分析、说明过程】
非递归实现的先序遍历 定义栈s,top表示栈顶指针 定义指向二叉树的指针p 如果是空二叉树,遍历结束 不是空二叉树则循环 While循环 当前指针p入栈 访问当前二叉树根节点 指针指向p的左孩子结点 如果栈空时结束 否则弹出栈顶元素 指针指向p的右孩子结点 非递归实现的中序遍历 定义栈s,top表示栈顶指针 定义指向二叉树的指针p 如果是空二叉树,遍历结束 不是空二叉树则循环 While循环 当前指针p入栈 指针指向p的左孩子结点 如果栈空时结束 否则弹出栈顶元素 访问当前二叉树根节点 指针指向p的右孩子结点 |
【思考问题】
二叉树是树的一种特殊形式。 二叉树由根节点、左子树和右子树组成,而左子树和右子树也是一棵二叉树,它们的定义与原二叉树的定义相同,因此可以使用递归的方式来定义二叉树。
先序遍历:先访问根节点 再访问左子树 最后访问右子树 中序遍历:先访问左子树 再访问根节点 最后访问右子树 后序遍历:先访问左子树 再访问右子树 最后访问根节点
使用递归:
文件系统 编译器 哈夫曼树 |
【实验小结】 (总结本次实验的重难点及心得、体会、收获)
本次实验学习了二叉树的遍历,创建 二叉树是一种特殊的树,遍历有先序中序和后序三种,以及递归和非递归方式。 |
【附录-实验代码】
基础篇 printf("%c",p->data); preorder(p->lchild); preorder(p->rchild); inorder(p->lchild); printf("%c",p->data); inorder(p->rchild); postorder(p->lchild); postorder(p->rchild); printf("%c",p->data); 提高篇 #include<stdio.h> #include<stdlib.h> #include<conio.h> #define MAXSIZE 100 typedef char elemtype; typedef struct bitree { elemtype data; struct bitree *lchild,*rchild; }BTREE; BTREE *create() {//非递归创建二叉树 BTREE *q[100]; //定义q数组作为队列存放二叉链表中结点,100为最大容量 BTREE *s; //二叉链表中的结点 BTREE *root ; //二叉链表的根指针 int front=1,rear=0,i; //定义队列的头、尾指针 char ch; //结点的data域值 root=NULL; for(i=0;i<100;i++) q[i]=NULL; printf("请按层次依次输入二叉树中的结点:\n"); printf("空结点以逗号代替,以#号结束!\n"); ch=getchar(); while(ch!='#') //输入值为#号,算法结束 { s=NULL; if(ch!=',') //输入数据不为逗号,表示不为虚结点,否则为虚结点 { s=(BTREE *)malloc(sizeof(BTREE)); s->data=ch; s->lchild=NULL; s->rchild=NULL; } rear++; q[rear]=s; //新结点或虚结点进队 if(rear==1) root=s; else { if((s!=NULL)&&(q[front]!=NULL)) { if(rear%2==0) q[front]->lchild=s; //rear为偶数,s为双亲左孩子 else q[front]->rchild=s; //rear为奇数,s为双亲右孩子 } if(rear%2==1) front++; //出队 } ch=getchar(); } return root; } void preorder(BTREE *root) {//非递归实现的先序遍历 BTREE *s[MAXSIZE],*p=root; int top=-1; if(p==NULL) return; do{ while(p!=NULL) { if(top>=MAXSIZE-1) { printf("栈溢出\n"); } s[++top]=p; printf("%c",p->data); p=p->lchild; } if(top==-1) return; else { p=s[top--]; p=p->rchild; } }while(p!=NULL||top!=-1); } void inorder(BTREE *root) {//非递归实现的中序遍历 BTREE *s[MAXSIZE],*p=root; int top=-1; if(p==NULL) return; do{ while(p!=NULL) { if(top>=MAXSIZE-1) { printf("栈溢出\n"); } s[++top]=p; p=p->lchild; } if(top==-1) return; else { p=s[top--]; printf("%c",p->data); p=p->rchild; } }while(p!=NULL||top!=-1); } void postorder(BTREE *root) {//非递归实现的后序遍历 BTREE *p,*s1[100]; //s1栈存放树中结点 int s2[100],top=0,b; //s2栈存放进栈标志 p=root; do { while(p!=NULL) { s1[top]=p; s2[top++]=0; //第一次进栈标志为0 p=p->lchild; } if(top>0) { b=s2[--top]; p=s1[top]; if(b==0) { s1[top]=p; s2[top++]=1; //第二次进栈标志为0 p=p->rchild; } else { printf("%c",p->data); p=NULL; } } }while(top>0); } void lorder(BTREE *root) {//非递归实现的层次遍历 BTREE *q[MAXSIZE],*p; // maxsize为最大容量 int f,r; // f,r类似于头尾指针 q[1]=root; f=r=1; while(f<=r) { p=q[f]; f++; //出队 printf("%c",p->data); if(p->lchild!=NULL) { r++; q[r]=p->lchild; } //入队 if(p->rchild!=NULL) { r++; q[r]=p->rchild; } //入队 } } void showmenu() {//显示菜单 printf(" 欢迎使用二叉树操作演示小软件\n"); printf("\t1、创建二叉树\n"); printf("\t2、先序遍历二叉树\n"); printf("\t3、中序遍历二叉树\n"); printf("\t4、后序遍历二叉树\n"); printf("\t5、层次遍历二叉树\n"); printf("\t6、退出程序\n"); } int main() { BTREE *root=NULL; int no; while(1) { showmenu(); printf(" 请输入你的选择:"); scanf("%d",&no); fflush(stdin);//清除键盘缓冲区 switch(no) { case 1:root=create(); printf("二叉树创建成功,按任意键继续…\n"); getch(); system("cls"); break; case 2:printf("二叉树先序遍历结果为:\n"); preorder(root); printf("\n"); system("pause"); system("cls"); break; case 3:printf("二叉树中序遍历结果为:\n"); inorder(root); printf("\n"); system("pause"); system("cls"); break; case 4:printf("二叉树后序遍历结果为:\n"); postorder(root); printf("\n"); system("pause"); system("cls"); break; case 5:printf("二叉树层次遍历结果为:\n"); lorder(root); printf("\n"); system("pause"); system("cls"); break; case 6:return 0; default: printf("你的输入有误,请从新输入!\n"); } } } |