实验三、二叉树的基本操作
实验三 二叉树基本操作

实验三二叉树基本操作(2课时)一、实验目的1.掌握二叉树的结构特征,以及各种存储结构的特点及使用范围。
2.掌握用指针类型描述、访问和处理二叉树的运算。
二、实验要求1.程序结构清晰、语句完整,包含有头文件和main函数;2.格式正确,语句采用缩进格式;3.运行结果正确,输入输出有提示,格式美观。
三、实验设备、材料和工具1.奔腾2计算机或以上机型2.turboc2,vc++,TC++四、实验内容和步骤实验内容:1.统计一棵二叉树中每种类型结点数(度为0、1、2的结点数)。
2.分别输入一棵有6个结点和8个结点的二叉树,编程序输出先序、中序和后序的遍历结果。
3.哈夫曼树及哈夫曼编码。
五、实验报告要求1.根据实验内容初步设计好程序,并从理论上排除错误;2.针对程序的健壮性准备好测试数据;3.结果分析中如实填写运行后的结果,并记录调试过程中产生的重要问题和解决方法。
六、根据实验过程填写下面内容1:程序:#include"test.h"int LeafCount1=0,LeafCount2=0,LeafCount3=0;void leaf_a(BiTree root){if(root!=NULL){leaf_a(root->LChild);leaf_a(root->RChild);if(root->LChild==NULL&&root->RChild==NULL)LeafCount1++;else if(root->LChild==NULL||root->RChild==NULL)LeafCount2++;else if(root->LChild!=NULL||root->RChild!=NULL)LeafCount3++;elseprintf("不符合题意!");}}void main(){BiTree root;printf("按先序遍历序列建立二叉树,请输入需要插入的序列:\n");CreateBiTree(&root);// PreOrder(root);leaf_a(root);printf("度为0的节点数:%d\n",LeafCount1);printf("度为1的节点数:%d\n",LeafCount2);printf("度为2的节点数:%d\n",LeafCount3);}#include <stdio.h>#include <malloc.h>#include <conio.h>typedef char DataType;void Visit(char ch){printf("%c ",ch);}typedef struct Node{DataType data;struct Node *LChild;struct Node *RChild;}BiTNode, *BiTree;void CreateBiTree(BiTree *bt){char ch;ch = getchar();if(ch=='#')*bt=NULL;else{*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点(*bt)->data=ch;CreateBiTree(&((*bt)->LChild)); //生成左子树CreateBiTree(&((*bt)->RChild)); //生成右子树}}void PreOrder(BiTree root)/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {if (root!=NULL){Visit(root->data); /*访问根结点*/PreOrder(root->LChild); /*先序遍历左子树*/PreOrder(root->RChild); /*先序遍历右子树*/ }}void InOrder(BiTree root)/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {if (root!=NULL){InOrder(root ->LChild); /*中序遍历左子树*/Visit(root ->data); /*访问根结点*/InOrder(root ->RChild); /*中序遍历右子树*/}}void PostOrder(BiTree root)/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/ {if(root!=NULL){PostOrder(root ->LChild); /*后序遍历左子树*/PostOrder(root ->RChild); /*后序遍历右子树*/Visit(root ->data); /*访问根结点*/}}结果分析:(要求完全理解程序,需每人答辩)ab cd ef2:程序:#include"bitree.h"void main(){BiTree T;char ch;printf("按照先序遍历建立二叉树,请输入序列:\n");CreateBiTree(&T);printf("\n先序遍历为:"); //先序遍历PreOrder(T);printf("\n中序遍历为:"); //中序遍历InOrder(T);printf("\n后序遍历为:"); //后序遍历PostOrder(T);}#include <stdio.h>#include <malloc.h>#include <conio.h>#define false 0#define true 1typedef char DataType;typedef struct Node{DataType data;struct Node *LChild;struct Node *RChild;}BiTNode, *BiTree;void CreateBiTree(BiTree *bt){char ch;ch=getchar();if(ch=='#')*bt=NULL;else{*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点(*bt)->data=ch;CreateBiTree(&((*bt)->LChild)); //生成左子树CreateBiTree(&((*bt)->RChild)); //生成右子树}}void PreOrder(BiTree root)/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {if (root!=NULL){printf("%c ",root ->data); /*访问根结点*/PreOrder(root ->LChild); /*先序遍历左子树*/PreOrder(root ->RChild); /*先序遍历右子树*/}}void InOrder(BiTree root)/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {if (root!=NULL){InOrder(root ->LChild); /*中序遍历左子树*/printf("%c ",root ->data); /*访问根结点*/InOrder(root ->RChild); /*中序遍历右子树*/}}void PostOrder(BiTree root)/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/ {if(root!=NULL){PostOrder(root ->LChild); /*后序遍历左子树*/PostOrder(root ->RChild); /*后序遍历右子树*/printf("%c ",root ->data); /*访问根结点*/}}结果分析:(要求完全理解程序,需每人答辩)第一个8个结点的二叉树图形为:b cef g h第二个为6个节点的二叉树图形:ab cd e f对结点的输出实现递归调用,输出各种遍历的情况3:程序:#include <stdio.h>#include <stdlib.h>#include <string.h>#include "huffman.h"//typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*//*typedef struct{unsigned int weight ; /* 用来存放各个结点的权值unsigned int parent, LChild,RChild ; //指向双亲、孩子结点的指针}HTNode, * HuffmanTree; //动态分配数组,存储哈夫曼树*///输出哈夫曼树void outputHuffman(HuffmanTree HT, int m){if(m!=0){printf("%d ", HT[m].weight);outputHuffman(HT,HT[m].LChild);outputHuffman(HT,HT[m].RChild);}}HuffmanTree HT; //ht哈夫曼树HuffmanCode HC; //hc哈弗曼编码int *w;int i,n; // 元素的个数;int wei; // 元素的权值;int m;printf("输入哈夫曼树的总结点树:" );scanf("%d",&n);w=(int *)malloc((n+1)*sizeof(int));for(i=1;i<=n;i++){printf("请输入第%d个元素的权值:",i);fflush(stdin);//清除缓存scanf("%d",&wei);w[i]=wei;}CrtHuffmanTree(&HT,w,n);m = 2*n-1;outputHuffman(HT,m);printf("\n");CrtHuffmanCode(&HT,&HC,n);}#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 20#define M 2*N-1typedef char* HuffmanCode[N+1];/*存储N个哈夫曼编码串的头指针数组*/{unsigned int weight ; /* 用来存放各个结点的权值*/unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/ }HTNode, HuffmanTree[M+1]; /*动态分配数组,存储哈夫曼树*/void select(HuffmanTree *ht,int n, int *s1, int *s2){int i;int min;for(i=1; i<=n; i++){if((*ht)[i].parent == 0){ min = i;i = n+1;}}for(i=1; i<=n; i++){if((*ht)[i].parent == 0){if((*ht)[i].weight < (*ht)[min].weight)min = i;}}*s1 = min;for(i=1; i<=n; i++){if((*ht)[i].parent == 0 && i!=(*s1)){ min = i;i = n+1;}}for(i=1; i<=n; i++){if((*ht)[i].parent == 0 && i!=(*s1)){if((*ht)[i].weight < (*ht)[min].weight)min = i;}}*s2 = min;}void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)/*从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码*/{char *cd;int i;unsigned int c;int start;int p;hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); /*分配n个编码的头指针*/cd=(char * )malloc(n * sizeof(char )); /*分配求当前编码的工作空间*/cd[n-1]='\0'; /*从右向左逐位存放编码,首先存放编码结束符*/for(i=1;i<=n;i++) /*求n个叶子结点对应的哈夫曼编码*/{start=n-2; /*初始化编码起始指针*/for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*从叶子到根结点求编码*/ if( (*ht)[p].LChild == c){cd[start]='0'; /*左分支标0*/--start;}else{cd[start]='1'; /*右分支标1*/--start;}(*hc)[i]=(char *)malloc((n-start)*sizeof(char)); /*为第i个编码分配空间*/strcpy((*hc)[i],&cd[start+1]);}free(cd);for(i=1;i<=n;i++)printf("%d编码为%s\n",(*ht)[i].weight,(*hc)[i]);}void CrtHuffmanTree(HuffmanTree *ht , int *w, int n){ /* w存放已知的n个权值,构造哈夫曼树ht */int m,i;int s1,s2;m=2*n-1;// *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0号单元未使用*/ for(i=1;i<=n;i++){/*1-n号放叶子结点,初始化*/(*ht)[i].weight = w[i];(*ht)[i].LChild = 0;(*ht)[i].parent = 0;(*ht)[i].RChild = 0;}for(i=n+1;i<=m;i++){(*ht)[i].weight = 0;(*ht)[i].LChild = 0;(*ht)[i].parent = 0;(*ht)[i].RChild = 0;} /*非叶子结点初始化*//* ------------初始化完毕!对应算法步骤1---------*/for(i=n+1;i<=m;i++) /*创建非叶子结点,建哈夫曼树*/{ /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/select(ht,i-1,&s1,&s2);(*ht)[s1].parent=i;(*ht)[s2].parent=i;(*ht)[i].LChild=s1;(*ht)[i].RChild=s2;(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;}}/*哈夫曼树建立完毕*/结果分析:(要求完全理解程序,需每人答辩)通过调用select函数找出最小的两个权值,用CrtHuffman函数存放权值构成哈夫曼树再调用CrtHuffmanCode函数实现从叶子结点到根,逆向求每个叶子结点对应的哈弗曼编码。
实验三二叉树基本操作与应用实验

实验三二叉树基本操作与应用实验第一篇:实验三二叉树基本操作与应用实验实验三二叉树基本操作与应用实验第三次实验主要包括两部分内容:1.二叉树基本操作实验;2.二叉树应用—赫夫曼树与赫夫曼编码实验。
基本操作包括存储结构建立和遍历算法,本文只给出部分参考程序,请大家尽量完成多数基本操作。
第一部分基本操作实验[问题描述] 二叉树采用二叉链表作存储结构,试编程实现二叉树的如下基本操作1.按先序序列构造一棵二叉链表表示的二叉树T;2.对这棵二叉树进行遍历:先序、中序、后序以及层次遍历序列,分别输出结点的遍历序列;3.求二叉树的深度,结点数目,叶结点数目; [数据描述] //二叉树的二叉链表存储表示先序遍历二叉树递归算法6.层次遍历二叉树的非递归算法7.求二叉树的深度[说明]1.按先序次序输入二叉树中结点的值,用‘#’表示空树,对每一个结点应当确定其左右子树的值(为空时必须用特定的空字符占位),故执行此程序时,最好先在纸上画出你想建立的二叉树,每个结点的左右子树必须确定。
若为空,则用特定字符标出,然后再按先序输入这棵二叉树的字符序列。
2.为了简化程序的书写量,以及程序的清晰性,对结点的访问以一条输出语句表示,若有更复杂的或多种访问,可以将结点的访问编写成函数,然后通过函数指针进行函数的调用。
读者若有兴趣,可自行编写。
3.c语言函数参数传递,都是以“传值”的方式,故在设计函数时,必须注意参数的传递。
若想通过函数修改实际参数的值,则必须用指针变量作参数。
具体设计时;读者一定要把指针变量及指针变量指向的值等概念弄清楚。
4.完整参考程序只给出了部分遍历算法,对于其他算法,请读者参照示例,自行编程完成,以加深学习体会。
对于二叉链表的建立也是如此,示例中只是给出了先序法建立过程,读者可自行练习中序、后序二叉链表建立法,叶子结点或二叉树结点总数求法等。
第二部分二叉树应用实验---------郝夫曼树与郝夫曼编码[问题描述] 利用HuffMan编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
二叉树的操作实验报告

二叉树的操作实验报告二叉树的操作实验报告引言二叉树是计算机科学中常用的数据结构,它具有良好的搜索性能和灵活的插入和删除操作。
本实验旨在通过实际操作,深入理解二叉树的基本操作和特性。
1. 二叉树的定义和基本概念二叉树是一种特殊的树状结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树的节点由数据和指向左右子节点的指针组成。
根据节点的位置,可以将二叉树分为左子树、右子树和根节点。
2. 二叉树的遍历二叉树的遍历是指按照一定的顺序访问二叉树中的所有节点。
常用的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历先访问根节点,然后按照左子树、右子树的顺序遍历;中序遍历先访问左子树,然后根节点,最后右子树;后序遍历先访问左子树,然后右子树,最后根节点。
3. 二叉树的插入操作插入操作是将一个新节点插入到二叉树中的特定位置。
插入操作需要考虑节点的大小关系,小于当前节点则插入到左子树,大于当前节点则插入到右子树。
插入操作可以保持二叉树的有序性。
4. 二叉树的删除操作删除操作是将指定节点从二叉树中删除。
删除操作需要考虑被删除节点的子节点情况,如果被删除节点没有子节点,则直接删除;如果有一个子节点,则将子节点替代被删除节点的位置;如果有两个子节点,则选择被删除节点的后继节点或前驱节点替代被删除节点。
5. 二叉树的查找操作查找操作是在二叉树中搜索指定的节点。
二叉树的查找操作可以使用递归或迭代的方式实现。
递归方式会自动遍历整个二叉树,直到找到目标节点或遍历完整个树。
迭代方式则需要手动比较节点的值,并根据大小关系选择左子树或右子树进行进一步查找。
6. 二叉树的平衡性二叉树的平衡性是指左子树和右子树的高度差不超过1。
平衡二叉树可以提高搜索效率,避免出现极端情况下的性能下降。
常见的平衡二叉树有AVL树和红黑树。
7. 二叉树应用场景二叉树在计算机科学中有广泛的应用场景。
例如,文件系统的目录结构可以使用二叉树来表示;数据库中的索引结构也可以使用二叉树来实现。
数据结构实验 二叉树的操作

实验三二叉树的操作一、实验目的1、掌握二叉树的逻辑结构;2、掌握二叉树的二叉链表存储结构;3、掌握基于二叉链表存储的二叉树的遍历操作的实现。
二、实验内容1、采用二叉链表存储建立一棵含有n个结点的二叉树;2、前序打印该二叉树的所有叶子结点;3、统计该二叉树的结点个数;4、计算该二叉树的深度;5、交换该二叉树的所有左右子树。
三、程序实现1、二叉链表结点类型BiNode.htemplate<class T>struct BiNode{T data;BiNode<T> *lchild,*rchild;};2、二叉树的建立及操作BiTree.htemplate<class T>struct BiNode{T data;BiNode<T> *lchild,*rchild;};template <class T>class BiTree{public:BiTree( ); //构造函数,初始化一棵二叉树,其前序序列由键盘输入~BiTree(); //析构函数,释放二叉链表中各结点的存储空间BiNode<T>* Getroot(); //获得指向根结点的指针void PreOrder(BiNode<T> *root); //前序遍历二叉树void InOrder(BiNode<T> *root); //中序遍历二叉树void PostOrder(BiNode<T> *root); //后序遍历二叉树void LevelOrder(BiNode<T> *root); //层序遍历二叉树private:BiNode<T> *root; //指向根结点的头指针BiNode<T>* Creat(); //有参构造函数调用void Release(BiNode<T> *root); //析构函数调用};template<class T>BiTree<T>::BiTree(){cout<<"请按前根序输入该二叉树的各个结点(#号表示为空):\n";this->root=Creat();}template <class T>BiNode<T>* BiTree<T>::Creat(){BiNode<T> *root;T ch;cin>>ch;if (ch=='#') root = NULL;else{root = new BiNode<T>; //生成一个结点root->data=ch;root->lchild=Creat(); //递归建立左子树root->rchild=Creat(); //递归建立右子树}return root;}template<class T>BiTree<T>::~BiTree(){Release(root);}template<class T>BiNode<T>* BiTree<T>::Getroot( ){return root;}template<class T>void BiTree<T>::PreOrder(BiNode<T> *root){if(root==NULL) return;else{cout<<root->data<<" ";PreOrder(root->lchild);PreOrder(root->rchild);}}template <class T>void BiTree<T>::InOrder (BiNode<T> *root){if (root==NULL) return; //递归调用的结束条件else{InOrder(root->lchild); //中序递归遍历root的左子树cout<<root->data<<" "; //访问根结点的数据域InOrder(root->rchild); //中序递归遍历root的右子树}}template <class T>void BiTree<T>::PostOrder(BiNode<T> *root){if (root==NULL) return; //递归调用的结束条件else{PostOrder(root->lchild); //后序递归遍历root的左子树PostOrder(root->rchild); //后序递归遍历root的右子树cout<<root->data<<" "; //访问根结点的数据域}}template <class T>void BiTree<T>::LevelOrder(BiNode<T> *root){const int MaxSize = 100;int front = 0;int rear = 0; //采用顺序队列,并假定不会发生上溢BiNode<T>* Q[MaxSize];BiNode<T>* q;if (root==NULL) return;else{Q[rear++] = root;while (front != rear){q = Q[front++];cout<<q->data<<" ";if (q->lchild != NULL) Q[rear++] = q->lchild;if (q->rchild != NULL) Q[rear++] = q->rchild;}}}template<class T>void BiTree<T>::Release(BiNode<T>* root){if (root != NULL){Release(root->lchild); //释放左子树Release(root->rchild); //释放右子树delete root;}}3、主程序实现#include<iostream.h>#include "BiTree.h"int SumNode(BiNode<char> *root)//统计二叉树结点个数{int sum;if(root==NULL)return 0;else{sum=SumNode(root->lchild)+1;sum+=SumNode(root->rchild);return sum;}}void PrePrint(BiNode<char> *root)//前序打印二叉树叶子结点{if(root==NULL) return;else{if(root->lchild==NULL&&root->rchild==NULL)cout<<root->data<<' ';PrePrint(root->lchild);PrePrint(root->rchild);}}int TreeDeepth(BiNode<char> *root)//计算二叉树的深度{int deepth;if(root==NULL) return 0;else{deepth=(TreeDeepth(root->lchild)+1)>(TreeDeepth(root->rchild)+1)?(TreeDeepth(root->lchi ld)+1):(TreeDeepth(root->rchild)+1);return deepth;}}void Changechild(BiNode<char> *root)//交换二叉树的所有左右子树{BiNode<char> *temp;if(root==NULL||(root->lchild==NULL&&root->rchild==NULL)) return;else{Changechild(root->lchild);Changechild(root->rchild);if(root->lchild==NULL){root->lchild=root->rchild;root->rchild=NULL;}if(root->rchild==NULL){root->rchild=root->lchild;root->lchild=NULL;}else{temp=root->lchild;root->lchild=root->rchild;root->rchild=temp;}}}void main(){BiTree<char> Q;int deepth,sum;cout<<"Q的前序遍历为:\n";Q.PreOrder(Q.Getroot());cout<<"\nQ的中序遍历为:\n";Q.InOrder(Q.Getroot());cout<<"\nQ的后序遍历为:\n";Q.PostOrder(Q.Getroot());cout<<"\nQ的层序遍历为:\n";Q.LevelOrder(Q.Getroot());sum=SumNode(Q.Getroot());cout<<"\n结点个数为:"<<sum<<endl;deepth=TreeDeepth(Q.Getroot());cout<<"该二叉树的深度为:"<<deepth<<endl;cout<<"该二叉树叶子结点的前序打印顺序为:"<<'\n';PrePrint(Q.Getroot());cout<<"\n交换前二叉树的层序遍历为:\n";Q.LevelOrder(Q.Getroot());Changechild(Q.Getroot());cout<<"\n交换后二叉树的层序遍历为:\n";Q.LevelOrder(Q.Getroot());cout<<endl;}四、运行结果输入的二叉树结点的前根序序列为:ABDG##H##E#I##CF#J###二叉树形式为 AB CD E FG H I运行结果:五、实验心得体会通过本次实验过程,自己熟悉了二叉树的一些基本操作,掌握二叉树的逻辑结构;二叉树的二叉链表存储结构;熟悉了基于二叉链表存储的二叉树的遍历操作。
二叉树的基本操作实验报告

二叉树的基本操作实验报告学号姓名实验日期 2012-12-26实验室计算机软件技术实验指导教师设备编号 401实验内容二叉树的基本操作一实验题目实现二叉树的基本操作的代码实现二实验目的1、掌握二叉树的基本特性2、掌握二叉树的先序、中序、后序的递归遍历算法3、通过求二叉树的深度、度为2的结点数和叶子结点数等算法三实习要求(1)认真阅读书上给出的算法(2)编写程序并独立调试四、给出二叉树的抽象数据类型ADT BinaryTree{//数据对象D:D是具有相同特性的数据元素的集合。
//数据关系R:// 若D=Φ,则R=Φ,称BinaryTree为空二叉树;// 若D?Φ,则R={H},H是如下二元关系;// (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; // (2)若D-{root}?Φ,则存在D-{root}={D1,Dr},且D1?Dr =Φ; // (3)若D1?Φ,则D1中存在惟一的元素x1,<root,x1>?H,且存在D1上的关系H1 ?H;若Dr?Φ,则Dr中存在惟一的元素xr,<root,xr>?H,且存在上的关系Hr ?H;H={<root,x1>,<root,xr>,H1,Hr};// (4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树。
//基本操作:CreateBiTree( &T, definition ) // 初始条件:definition给出二叉树T的定义。
// 操作结果:按definiton构造二叉树T。
BiTreeDepth( T )// 初始条件:二叉树T存在。
// 操作结果:返回T的深度。
PreOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。
实验三二叉树的操作

实验三二叉树的操作实验三二叉树的操作一.实验目的1、基本要求:深刻理解二叉树性质和及各种存储结构的特点及适用范围;掌握用指针类型描述、访问和处理二叉树的运算;熟练掌握二叉树的遍历算法;2、较高要求: 在遍历算法的基础上设计二叉树更复杂操作算法;认识哈夫曼树、哈夫曼编码的作用和意义;掌握树与森林的存储与便利。
二. 实验学时:课内实验学时:3学时课外实验学时:6学时三.备选实验题目1.以二叉链表为存储结构,实现二叉树的创建、遍历(实验类型:验证型)1)问题描述:在主程序中设计一个简单的菜单,分别调用相应的函数功能:1…建立树2…前序遍历树3…中序(非递归)遍历树4…后序遍历树0…结束2)实验要求:在程序中定义下述函数,并实现要求的函数功能:CreateTree(): 按从键盘输入的前序序列,创建树PreOrderTree():前序遍历树(递归)InOrderTree():中序(非递归)遍历树LaOrderTree(): 后序遍历树(递归)3)实验提示:二叉链表存储数据类型定义# define ElemType char //元素类型typedef struct BiTNode{ ElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;元素类型可以根据实际情况选取。
4)注意问题:注意理解递归算法的执行步骤。
注意字符类型数据在输入时的处理。
重点理解如何利用栈结构实现非递归算法2.编写算法交换二叉树中所有结点的左、右子树(实验类型:综合型)1)问题描述:编写一算法,交换二叉树中所有结点的左、右子树2)实验要求:以二叉链表作为存储结构3) 实现提示:设二叉树的根指针未t,且以二叉链表表示,可利用一个类型为seqstack的指针来实现,且栈单元包含两个域,一个为data,另一个为top,整个栈容量为maxsize,当树非空时,将当前的树根结点入栈,同时将当前栈顶元素出栈当作根结点,然后依据当前的根结点是否具有孩子结点来判定是否将其左、右指针进行交换;再将交换后的左指针或右指针入栈,这样反复进行,直到栈空为止。
实验二 二叉树的基本操作

实验三二叉树的基本操作一、实验目的1、进一步掌握树的结构及非线性特点,递归特点和动态性。
2、掌握二叉树的建立算法。
3、掌握二叉树的三种遍历方法以及基于遍历的几种基本操作。
二、实验内容1、二叉树的链式存储结构的建立;2、二叉树的三种遍历算法以及基于遍历的几种操作的实现。
三、实验要求1、学生用C++/C完成算法设计和程序设计并上机调试通过;2、撰写实验报告,提供实验测试数据和实验结果;3、分析算法,要求给出具体的算法分析结果,包括时间复杂度和空间复杂度,并简要给出算法设计小结和心得。
四、实验准备1、了解树的结构特点及概念、二叉树的概念及结构特点。
2、了解树和二叉树的基本概念和术语。
3、二叉树的三种遍历方法(先序、中序、后序遍历)先序遍历:若二叉树为空,则空操作,否则①访问根结点;②先序遍历左子树;③先序遍历右子树。
中序遍历:若二叉树为空,则空操作,否则①中序遍历左子树;②访问根结点;③中序遍历右子树。
后序遍历:若二叉树为空,则空操作,否则①后序遍历左子树;②后序遍历右子树;③访问根结点。
4、二叉树的各种存储结构及其适用范围,特别是链式存储结构。
五、实验步骤1、编程实现二叉树的建立、遍历以及基于遍历的几种基本操作。
(1)采用二叉链表存储结构创建一个二叉树;(2)用递归方法实现二叉树的三种遍历算法(3)求二叉树中叶子结点的个数,度为1 的结点个数和度为2 的结点个数;(4)求二叉树的深度。
六、实验参考代码#include "iostream.h"#include "stdio.h"#include "stdlib.h"#define OK 1#define ERROR 0#define OVERFLOW -2#define NULL 0typedef char TElemType; //限定元素的数据类型typedef int Status;typedef struct BiTNode // 定义二叉树结点结构{TElemType data;BiTNode *lchild, *rchild; // 左右孩子指针} BiTNode, *BiTree;//按扩展的前序序列建立二叉树存储结构的算法Status CreateBiTree(BiTree &T){char ch;scanf("%c",&ch);if (ch=='#') T = NULL;else{if (!(T = (BiTNode *)malloc(sizeof(BiTNode)))) exit(OVERFLOW);T->data = ch; // 生成根结点CreateBiTree(T->lchild); // 构造左子树CreateBiTree(T->rchild); // 构造右子树}return OK;} // CreateBiTree// 先序遍历二叉树void PreOrder (BiTree T){if (T) {printf("%4c",T->data); // 访问结点PreOrder(T->lchild); // 遍历左子树PreOrder(T->rchild) ; // 遍历右子树}}// 中序遍历二叉树void InOrder (BiTree T){if (T){InOrder(T->lchild); // 遍历左子树printf("%4c",T->data); // 访问结点InOrder(T->rchild);// 遍历右子树}}// 后序遍历二叉树void PostOrder (BiTree T){if (T) {PostOrder (T->lchild); // 遍历左子树PostOrder (T->rchild);// 遍历右子树printf("%4c",T->data); // 访问结点}}//求二叉树的叶子结点数void CountLeaf (BiTree T, int& count){if(T){if((!T->lchild)&&(!T->rchild)) count++;CountLeaf(T->lchild,count);CountLeaf(T->rchild,count);}}//求二叉树中度为1的结点和度为2 的结点的数void CountBT(BiTree T,int &m,int &n){if(T){if((T->lchild!=0)&&(T->rchild!=0))n++; //度为2的结点else if(((T->lchild!=0)&&(T->rchild==0))||((T->lchild==0)&&(T->rchild!=0)))m++; //度为1 的结点CountBT (T->lchild,m,n);CountBT (T->rchild,m,n);}}//以下是求二叉树的深度int Depth (BiTree T ){int m,n;if(!T) return 0;else{m = Depth(T->lchild);n = Depth(T->rchild);return (m>n?m:n)+1;}}//主函数void main(){BiTree T;int s=0,m=0,n=0,d=0;T=NULL;int select;while(1) {printf("\n 请选择要执行的操作:\n");printf("1.创建二叉树\n");printf("2.二叉树的递归遍历算法(前、中、后)\n");printf("3.求二叉树的叶子结点数\n");printf("4.求二叉树的深度\n");printf("0.退出\n");scanf("%d",&select);getchar();switch(select) {case 0:return;case 1:printf("\n 请按先序次序输入各结点的值,以#表示空树:\n");CreateBiTree(T);printf("二叉树已建立完毕!\n");break;case 2:if(!T) printf("\n 未建立树,请先建树!\n");else {printf("\n 先序遍历:");PreOrder(T);printf("\n 中序遍历:");InOrder(T);printf("\n 后序遍历:");PostOrder(T);printf("\n");}break;case 3:if(!T) printf("\n 未建立树,请先建树!\n");else{CountLeaf(T,s);printf("\n 叶子结点数为:%d\n",s);CountBT(T,m,n);printf("度为1的结点数为:%d\n",m);printf("度为2 的结点数为:%d\n",n);}break;case 4:if(!T) printf("\n 未建立树,请先建树!\n");else{d=Depth(T);printf("\n 二叉树的深度为:%d\n",d);}break;default:printf("请确认选择项:\n");}//end switch}//end while}七、测试数据教材138 页,图7-10所示的二叉树按展的前序序列输入序列为:A B D # G # # # C E # # F H # # #。
数据结构 实验三 -二叉树的操作及应用

实验三二叉树的操作及应用实验课程名:数据结构与算法专业班级:计算机科学与技术(1)班学号:姓名:实验时间:12.11 实验地点:指导教师:一、实验目的1、进一步掌握指针变量、动态变量的含义。
2、掌握二叉树的结构特性,以及各种存储结构的特点和适用范围。
3、掌握用指针类型描述、访问和处理二叉树的运算。
二、实验任务1、分别以顺序存储结构和二叉链表作存储结构,试编程实现前序、中序、后序及层次顺序遍历二叉树的算法。
程序源代码:#include <stdio.h>#include <malloc.h>#define NULL 0typedef struct node{int data;struct node *lchild,*rchild;}BiT ree;int front=0,rear=0;BiT ree *q[10];//创建二叉树BiT ree *CreatBiT ree(){int x;BiT ree *T;scanf("%d",&x);if(x==0)T=NULL;else{T=(BiT ree *)malloc(sizeof(BiT ree));T->data=x;T->lchild=CreatBiT ree();T->rchild=CreatBiT ree();}return (T);}//先序遍历void Pre(BiT ree *T){if(T!=NULL){printf("%4d",T->data);Pre(T->lchild);Pre(T->rchild);}}//中序遍历void In(BiT ree *T){if(T!=NULL){In(T->lchild);printf("%4d",T->data);In(T->rchild);}}//后序遍历void Back(BiT ree *T){if(T!=NULL){Back(T->lchild);Back(T->rchild);printf("%4d",T->data);}}void enqueue(BiT ree *t){if(front!=rear+1){rear=rear+1;q[rear]=t;}}BiT ree *delqueue(){if(front==rear)return NULL;{front=front+1;return (q[front]);}}void lev(BiT ree *t){BiT ree *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);}}}void main(){int i;BiT ree *t;printf("Please enter value:\t");t=CreatBiT ree();printf("0:退出\t1:先序\t2:中序\t3:后序\t4:层次\n");do{printf("Please choose the num:\t");scanf("%d",&i);switch(i){case 0:break;case 1:{Pre(t);printf("\n");break;}case 2:{In(t);printf("\n");break;}case 3:{Back(t);printf("\n");break;}case 4:{lev(t);printf("\n");break;}default:printf("Input Error!\n");}}while(i);printf("\n");}程序运行结果:2、以二叉链表作存储结构,试编写计算二叉树深度、所有结点总数、叶子结点数、双孩子结点个数、单孩子结点个数的算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三二叉树的基本运算
一、实验目的
1、使学生熟练掌握二叉树的逻辑结构和存储结构。
2、熟练掌握二叉树的各种遍历算法。
二、实验内容
题目一:二叉树的基本操作实现(必做题)
[问题描述]
建立一棵二叉树,试编程实现二叉树的如下基本操作:
1. 按先序序列构造一棵二叉链表表示的二叉树T;
2. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列;
3. 求二叉树的深度/结点数目/叶结点数目;(选做)
4. 将二叉树每个结点的左右子树交换位置。
(选做)
[基本要求]
从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),
[测试数据]
如输入:ABCффDEфGффFффф(其中ф表示空格字符)
则输出结果为
先序:ABCDEGF
中序:CBEGDFA
后序:CGEFDBA
层序:ABCDEFG
[选作内容]
采用非递归算法实现二叉树遍历。
三、算法设计
1、主要思想:根据二叉树的图形结构创建出二叉树的数据结构,然后
用指针对树进行操作,重点掌握二叉树的结构和性质。
2、本程序包含四个模块:
(1)结构体定义
(2)创建二叉树
(3)对树的几个操作
(4)主函数
四、调试分析
这是一个比较简单程序,调试过程中并没有出现什么问题,思路比较清晰
五、实验结果
六、总结
此次上机实验对二叉树进行了以一次实际操作,让我对二叉树
有了更深的了解,对二叉树的特性有了更熟悉的认知,让我知
道了二叉树的重要性和便利性,这对以后的编程有更好的帮助。
七、源程序
#include<iostream>
#include<queue>
using namespace std;
#define TElemType char
#define Status int
#define OK 1
#define ERROR 0
typedef struct BiTNode{
TElemType data;
struct BiTNode * lchild, *rchild;
}BiTNode,* BiTree;
Status CreateBiTree(BiTree &T)
{
TElemType ch;
cin >> ch;
if (ch == '#')
T = NULL;
else
{
if (!(T = (BiTNode *)malloc(sizeof(BiTNode))))
exit(OVERFLOW);
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}
Status PreOrderTraverse(BiTree T)
{
if (T)
{
cout << T->data;
if (PreOrderTraverse(T->lchild))
if (PreOrderTraverse(T->rchild))
return OK;
return ERROR;
}
else
return OK;
}
Status InOrderTraverse(BiTree T)
{
if (T)
{
InOrderTraverse(T->lchild);
cout << T->data;
InOrderTraverse(T->rchild);
}
return OK;
}
Status PostOrderTraverse(BiTree T)
{
if (T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout << T->data;
}
return OK;
}
Status leOrderTraverse(BiTree T)
std::queue<BiTree> Q;
if (T == NULL)return ERROR;
else{
(T);
while (!())
{
T = ();
();
cout << T->data;
if (T->lchild != NULL)
(T->lchild);
if (T->rchild != NULL)
(T->rchild);
}
}
return OK;
}
Status change(BiTree T)
{
BiTree temp = NULL;
if (T->lchild == NULL && T->rchild == NULL) return OK;
else{
temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
}
if (T->lchild)
change(T->lchild);
if (T->rchild)
change(T->rchild);
return OK;
}
int FindTreeDeep(BiTree T){
int deep = 0;
if (T){
int lchilddeep = FindTreeDeep(T->lchild);
int rchilddeep = FindTreeDeep(T->rchild);
deep = lchilddeep >= rchilddeep lchilddeep + 1 : rchilddeep + 1;
}
return deep;
}
int main()
{
BiTree T;
CreateBiTree(T);
cout << "先序遍历顺序为:";
PreOrderTraverse(T);
cout << endl;
cout << "中序遍历顺序为:";
InOrderTraverse(T);
cout << endl;
cout << "后序遍历顺序为:";
PostOrderTraverse(T);
cout << endl;
cout << "层序遍历顺序为:";
leOrderTraverse(T);
cout << endl;
cout << "二叉树深度为:" << FindTreeDeep(T)<<endl;
cout << "左右子树交换后:";
change(T);
cout << "先序遍历顺序为:";
PreOrderTraverse(T);
cout << endl;
return 0;
}。