北邮数据结构实验—二叉排序树
数据结构_二叉排序树实验报告
日 期:
实验成绩:
批阅日期:
【本文档内容可以自由复制内容或自由编辑修改内容期待你的好评和关注,我们将会做得更好】
五、概要设计
为了实现上述操作,应以构造体为存储构造。实现如下:
struct node
{
int key;//关键字的值
struct node *lchild,*rchild;//左右指针
}BSTNode,*BSTree;
1、根本操作:
〔1〕struct node
{
int key;//关键字的值
struct node *lchild,*rchild;//左右指针
2、输出的形式:建立好的排序二叉树的中序遍历结果。
3、程序所能到达的功能:能够通过键盘输入建立二叉排序树,并在建立完立即在屏幕显示中序遍历结果的程序
4、测试数据:输入45 24 53 12 28 90并用空格将数隔开,以0作为完毕符,如:
输入45 24 53 12 28 90
输出的中序遍历结果为:12 24 28 45 53 90
}BSTNode,*BSTree;
void InsertBST(BSTree *bst,int key) //二叉排序树的插入结点
{
BSTree s;
if(*bst==NULL)
{
s=(BSTree)malloc(sizeof(BSTNode));
s->key=key;
s->lchild=NULL;
{
if(bt!=NULL)
{
inorder(bt->lchild);
printf("%3d",bt->key) ;
inorder(bt->rchild);
北邮数据结构平衡二叉树报告概论
数据结构实验报告实验名称:平衡二叉树1.实验目的和内容根据平衡二叉树的抽象数据类型的定义,使用二叉链表实现一个平衡二叉树。
二叉树的基本功能:1、平衡二叉树的建立2、平衡二叉树的查找3、平衡二叉树的插入4、平衡二叉树的删除5、平衡二叉树的销毁6、其他:自定义操作编写测试main()函数测试平衡二叉树的正确性。
2. 程序分析2.1 存储结构struct node{int key; //值int height; //这个结点的父节点在这枝最长路径上的结点个数node *left; //左孩子指针node *right; //右孩子指针node(int k){ key = k; left = right = 0; height = 1; } //构造函数};2.2 程序流程2.3 关键算法分析(由于函数过多,在此只挑选部分重要函数)算法1:void AVL_Tree::left_rotate(node *&x)[1] 算法功能:对 R-R型进行调整[2] 算法基本思想:将结点右孩子进行逆时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->right; y为x的右孩子x->right = y->left; 将y的左孩子赋给x的右孩子 y->left = x; x变为y的左孩子fixheight(x); 修正x,y的height值fixheight(y);x = y; 使x的父节点指向y 算法2:void A VL_Tree::right_rotate(node *&x)[1] 算法功能:对L-L型进行调整[2] 算法基本思想:将左孩子进行顺时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->left; //y为x的左孩子 x->left = y->right; y的右孩子赋给x的左孩子y->right = x; x变为y的右孩子fixheight(x); 修正x和y的height值fixheight(y);x = y; 使x的父节点指向y算法3:node*& A VL_Tree::balance(node *&p)[1] 算法功能:对给定结点进行平衡操作[2] 算法基本思想:通过平衡因子判断属于哪种情况,再依照情况进行平衡[3] 算法空间、时间复杂度分析:没有递归和循环,都为O(1)[4] 代码逻辑fixheight(p); //修正P的height值if (bfactor(p) == 2) 平衡因子为2,为L-?型if (bfactor(p->left) < 0) P的左孩子平衡因子<0时,为L-R型,执行left_rotate(p->left); 相关平衡操作,若>0,为L-L型。
二叉排序树的实验报告
二叉排序树的实验报告二叉排序树的实验报告引言:二叉排序树(Binary Search Tree,简称BST)是一种常用的数据结构,它将数据按照一定的规则组织起来,便于快速的查找、插入和删除操作。
本次实验旨在深入了解二叉排序树的原理和实现,并通过实验验证其性能和效果。
一、实验背景二叉排序树是一种二叉树,其中每个节点的值大于其左子树的所有节点的值,小于其右子树的所有节点的值。
这种特性使得在二叉排序树中进行查找操作时,可以通过比较节点的值来确定查找的方向,从而提高查找效率。
二、实验目的1. 理解二叉排序树的基本原理和性质;2. 掌握二叉排序树的构建、插入和删除操作;3. 验证二叉排序树在查找、插入和删除等操作中的性能和效果。
三、实验过程1. 构建二叉排序树首先,我们需要构建一个空的二叉排序树。
在构建过程中,我们可以选择一个节点作为根节点,并将其他节点插入到树中。
插入节点时,根据节点的值与当前节点的值进行比较,如果小于当前节点的值,则将其插入到当前节点的左子树中;如果大于当前节点的值,则将其插入到当前节点的右子树中。
重复这个过程,直到所有节点都被插入到树中。
2. 插入节点在已有的二叉排序树中插入新的节点时,我们需要遵循一定的规则。
首先,从根节点开始,将新节点的值与当前节点的值进行比较。
如果小于当前节点的值,则将其插入到当前节点的左子树中;如果大于当前节点的值,则将其插入到当前节点的右子树中。
如果新节点的值与当前节点的值相等,则不进行插入操作。
3. 删除节点在二叉排序树中删除节点时,我们需要考虑不同的情况。
如果要删除的节点是叶子节点,即没有左右子树,我们可以直接删除该节点。
如果要删除的节点只有一个子树,我们可以将子树连接到要删除节点的父节点上。
如果要删除的节点有两个子树,我们可以选择将其右子树中的最小节点或左子树中的最大节点替代该节点,并删除相应的替代节点。
四、实验结果通过对二叉排序树的构建、插入和删除操作的实验,我们得到了以下结果:1. 二叉排序树可以高效地进行查找操作。
数据结构二叉排序树实验报告
实验报告课程名:数据结构(C语言版)实验名:二叉排序树姓名:班级:学号:撰写时间:一实验目的与要求1.掌握二叉排序树上进行插入和删除的操作2.利用 C 语言实现该操作二实验内容•对于一个线形表, 利用不断插入的方法, 建立起一株二叉排序树•从该二叉排序树中删除一个叶子节点, 一个只有一个子树的非叶子节,一个有两个子树的非叶子节点。
三实验结果与分析#include<>#include<>删结点是叶子结点,直接删除if(p->left == NULL && p->right == NULL){删结点只有左子树else if(p->left && !(p->right)){p->left->parent=p->parent;删结点只有右孩子else if(p->right && !(p->left)){p->right->parent=p->parent;删除的结点既有左孩子,又有右孩子//该结点的后继结点肯定无左子树(参考上面查找后继结点函数)//删掉后继结点,后继结点的值代替该结点else{//找到要删除结点的后继q=searchSuccessor(p);temp=q->key;//删除后继结点deleteNode(root,q->key);p->key=temp;}return 1;}//创建一棵二叉查找树void create(PNode* root,KeyType *keyArray,int length) {int i;//逐个结点插入二叉树中for(i=0;i<length;i++)inseart(root,keyArray[i]);}int main(void){int i;PNode root=NULL;KeyType nodeArray[11]={15,6,18,3,7,17,20,2,4,13,9}; create(&root,nodeArray,11);for(i=0;i<2;i++)deleteNode(&root,nodeArray[i]);printf("%d\n",searchPredecessor(root)->key);printf("%d\n",searchSuccessor(root)->key);printf("%d\n",searchMin(root)->key);printf("%d\n",searchMax(root)->key);printf("%d\n",search(root,13)->key);return 0;}图1:二叉树排序实验结果。
二叉排序树实验报告
二叉排序树的实现一、实验内容与要求1)实现二叉排序树,包括生成、插入,删除;2)对二叉排序树进行先根、中根、和后根非递归遍历;3)每次对树的修改操作和遍历操作的显示结果都需要在屏幕上用树的形状表示出来。
二、实验方案1.选择链表的方式来构造节点,存储二叉排序树的节点。
//树的结构struct BSTNode{//定义左右孩子指针struct BSTNode *lchild,*rchild;//节点的关键字TElemType key;};int depth=0;//定义一个 struct BSTNode 类型的指针typedef BSTNode *Tree;2.对树的操作有如下方法:// 创建二叉排序树Tree CreatTree(Tree T);//二叉树的深度,返回一个int值为该树的深度int TreeDepth(Tree T)//树状输出二叉树,竖向输出void PrintTree(Tree T , int layer);//查找关键字,如果关键字存在则返回所在节点的父节点,如果关键字不存在则返回叶子所在的节点Status SearchBST(Tree T , TElemType key , Tree f,Tree &p);//向树中插入节点Status InsertBST(Tree &T , TElemType e);//删除节点Status Delete(Tree &T);//删除指定节点,调用Delete(Tree &T)方法Status DeleteData(Tree &T , TElemType key);//非递归先序遍历void x_print(Tree T);//非递归中序遍历Void z_print(Tree T );//非递归后序遍历void h_print(Tree T);3.对二叉排序树非递归先根、中根、后根遍历,采用栈来存储一次遍历过的节点的形式来辅助实现//自定义类型以 SElemType作为栈中指针返回的值的类型//也就是要返回一个节点的指针typedef Tree SElemType;//栈的结构struct Stack{//栈底指针SElemType *base;//栈顶指针SElemType *top;//栈的容量int stacksize;};4.栈的操作方法://创建一个空栈Status InitStack(Stack &S);//获取栈顶元素并删除栈中该位置的元素SElemType Pop(Stack &S,SElemType &elem)//获取栈顶元素返回栈顶元素不对栈做任何修改SElemType getTop(Stack S,SElemType &elem)//删除栈顶元素Status DeleteTop(Stack &S)//往栈中压入数据Status Push(Stack &S,SElemType elem)//判断栈是否为空Status IsEmpty(Stack S)三、代码实现#include <iostream>#include <math.h>using namespace std;//定义宏#define OK 1#define ERROR 0#define STACK_INIT_SIZE 10#define STACK_INCREMENT 2//定义宏分别为栈的初始容量和栈的增加容量#define STACK_INIT_SIZE 10#define STACK_INCREMENT 2typedef int TElemType;//树的结构struct BSTNode{//定义左右孩子指针struct BSTNode *lchild,*rchild;//节点的关键字TElemType key;};int depth=0;//定义一个 struct BSTNode 类型的指针typedef BSTNode *Tree;//自定义类型以 SElemType作为栈中指针返回的值的类型//也就是要返回一个节点的指针typedef Tree SElemType;//栈的结构struct Stack{//栈底指针SElemType *base;//栈顶指针SElemType *top;//栈的容量int stacksize;};//自定义类型typedef int Status;//创建一个空栈Status InitStack(Stack &S){//给栈指针分配空间S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));//如果分配空间失败则退出if(!S.base)exit(OVERFLOW);//栈底、栈顶指针相等表示栈为空//S.base=S.top;//此句代码若以如上句格式则在执行时会出现内存非法访问的错误S.top=S.base;//初始化栈的容量S.stacksize=STACK_INIT_SIZE;return OK;}//获取栈顶元素并删除栈中该位置的元素SElemType Pop(Stack &S,SElemType &elem){if(S.top==S.base){cout<<"gai zhan yi jing wei kong "<<endl;return ERROR;}else{elem=*--S.top;}return elem;}//获取栈顶元素返回栈顶元素不对栈做任何修改SElemType getTop(Stack S,SElemType &elem){//如果为空栈则返回ERRORif(S.base==S.top){cout<<"gai zhan yi jing wei kong"<<endl;return ERROR;}//如果栈不为空则返回栈顶元素else{elem=*(S.top-1);}return elem;}//删除栈顶元素Status DeleteTop(Stack &S){//判断栈是否为空if(S.base==S.top){cout<<"gai zhan yi jing wei kong "<<endl;return ERROR;}//如果栈不为空则删除栈顶元素else{--S.top;}return OK;}//往栈中压入数据Status Push(Stack &S,SElemType elem){//如果栈的容量超过初始化容量则增加栈的容量if(S.top-S.base>=S.stacksize){S.base=(SElemType*)realloc(S.base,(S.stacksize+STACK_INCREMENT)*sizeof(SElemType));if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACK_INCREMENT;}//添加数据*S.top++=elem;return OK;}//判断栈是否为空Status IsEmpty(Stack S){if(S.base==S.top)return OK;elsereturn ERROR;}/////////////////////////////////////////////////////////////////// ///////////以下的代码主要是对树的操作///////////////////////////// /////////////////////////////////////////////////////////////////////创建空树Status InitTree(Tree &T){T=NULL;return OK;}//查找关键字//如果关键字存在则返回所在节点的父节点//如果关键字不存在则返回叶子所在的节点Status SearchBST(Tree T,TElemType key,Tree f,Tree &p) {if(!T){p=f;return ERROR;}else if(T->key==key){p=T;return OK;}else if(T->key>key)return SearchBST(T->lchild,key,T,p);else if(T->key<key)return SearchBST(T->rchild,key,T,p);}//向树中插入节点Status InsertBST(Tree &T,TElemType e){Tree p;if(!SearchBST(T,e,NULL,p)){Tree s=(Tree)malloc(sizeof(BSTNode));s->key=e;s->lchild=s->rchild=NULL;if(!p){T=s;}else if(p->key>e){p->lchild=s;}else if(p->key<e){p->rchild=s;}}elsereturn ERROR;}// 创建二叉排序树Tree CreatTree(Tree T){TElemType elem;cout<<"请输入数据,以0结束输入操作"<<endl;cin>>elem;while(elem!=0 && elem>0){int k= InsertBST(T,elem);if(k){cout<<"请输入数据,以0结束输入操作"<<endl;cin>>elem;}else{cout<<"插入错误或存在重复元素"<<endl;//异常退出return ERROR;}}return T;}//删除节点Status Delete(Tree &T){Tree p,q;if(T->lchild!=NULL && T->rchild!=NULL){p=T;q=T->lchild;T=q;while(q->rchild!=NULL){q=q->rchild;}q->rchild=p->rchild;free(p);return OK;}if(T->rchild==NULL && T->lchild!=NULL){p=T;T=T->lchild;free(p);return OK;}else if(T->lchild==NULL && T->rchild!=NULL) {p=T;T=T->rchild;free(p);return OK;}else if(T->rchild==NULL && T->lchild==NULL){T=NULL;free(T);return OK;}}//删除指定节点Status DeleteData(Tree &T,TElemType key){if(!T){cout<<"找不到要删除的元素,请重新选择!"<<endl;return ERROR;}if(T->key==key){Delete(T);}else if(T->key>key)DeleteData(T->lchild,key);else if(T->key<key)DeleteData(T->rchild,key);return OK;}//先序遍历void x_print(Tree T){//Tree f;Stack S;InitStack(S);if(T==NULL){cout<<"树为空"<<endl;}while(T!=NULL || !IsEmpty(S)){if(T!=NULL){cout<<T->key<<" ";Push(S,T);T=T->lchild;}else{Pop(S,T);T=T->rchild;}}}//z中序遍历void z_print(Tree T ){// Tree f;Stack S;InitStack(S);if(T==NULL){cout<<"树为空"<<endl;}while(T!=NULL || !IsEmpty(S)){if(T!=NULL){Push(S,T);T=T->lchild;}else{Pop(S,T);cout<<T->key<<" ";T=T->rchild;}}}//后序遍历void h_print(Tree T){Stack S;InitStack(S);Tree f=NULL;if(T==NULL){cout<<"树为空"<<endl;}while(T!=NULL || !IsEmpty(S)){while(T!=NULL){Push(S,T);T=T->lchild;}getTop(S,T);if(T->rchild==NULL || T->rchild==f){cout<<T->key<<" ";Pop(S,f);T=NULL;}else{T=T->rchild;}}}//二叉树的深度int TreeDepth(Tree T){int left,right,max;if(T!=NULL){left=TreeDepth(T->lchild);right=TreeDepth(T->rchild);max=left>right?left:right;return max+1;}else{return ERROR;}}//竖向输出//树状输出二叉树void PrintTree(Tree T,int layer){int k;if(T==NULL)return ;PrintTree(T->rchild,layer+1);for(k=0;k<layer;k++)cout<<" ";cout<<T->key<<"\n";PrintTree(T->lchild,layer+1);}void main(){int key;int h;Tree tree;InitTree(tree);tree=CreatTree(tree);h=TreeDepth(tree);cout<<"树状输出为:"<<endl;PrintTree(tree,h);if(!tree){exit(-1);}cout<<"\n\n---------------请输入你要选择的操作--------------------\n"<<endl;cout<<"a.删除二叉树中的元素 b.向二叉树中添加元素"<<endl;cout<<"c.先根遍历二叉树 d.中根遍历二叉树 "<<endl;cout<<"e.后根遍历二叉树 o.退出操作 "<<endl;cout<<"\n\n------------------------------------------------------\n"<<endl;//int key;char select;cin>>select;while(select!='o'){switch(select){case 'o':exit(0);break;case 'a':if(!tree){cout<<"树以为空,请重新选择操作!"<<endl;cin>>select;}else{cout<<"请输入要删除的元素"<<endl;cin>>key;DeleteData(tree,key);cout<<"树状输出为:"<<endl;PrintTree(tree,h);}break;case 'b':cout<<"请输入要插入的元素"<<endl;cin>>key;InsertBST(tree,key);cout<<"树状输出为:"<<endl;PrintTree(tree,h);break;case 'c':cout<<"先根遍历结果为:"<<endl;x_print(tree);cout<<endl;break;case 'd':cout<<"中根遍历结果为:"<<endl;z_print(tree);cout<<endl;break;case 'e':cout<<"后根遍历结果为:"<<endl;h_print(tree);cout<<endl;break;default:cout<<"输入错误"<<endl;exit(-1);break;}cout<<"---------------请输入你要选择的操作--------------------"<<endl;cout<<"a.删除二叉树中的元素 b.向二叉树中添加元素"<<endl;cout<<"c.先根遍历二叉树 d.中根遍历二叉树 "<<endl;cout<<"e.后根遍历二叉树 o.退出操作 "<<endl;cout<<"--------------------------------------------------------"<<endl;cin>>select;}}四、实验结果和数据处理输入数据同选择操作结果如上图所示操作现象:输入操作的时候如果输入的不是数值(比如字母)就会出现插入操作错误的提示,然后异常退出操作;或者当输入的关键字已在树中存在,也会提示“重复输入”然后异常退出(这点存在不足,应该修改为提示之后重新输入操作)删除现象:如果要删除的关键字不存在则会提示不存在该关键字然后重新输入,如果树为空则会提示树为空并重新选择操作遍历现象:如果树为空,则不会退出操作,而是提示“树为空”。
北京邮电大学 数据结构 实验二 二叉树 可视化设计
数据结构实验报告实验名称:实验2——二叉树的构造学生姓名:XXXXNB班级:XXXXXX班内序号:学号:XXXXXXX日期:XXXXXXXX1.实验要求根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。
二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2.程序分析2.1 存储结构采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包含三个元素,分别是一个T 类型的数据域data,一个指向T 类型的指针左孩子,一个指向T 类型的指针右孩子,示意图如图所示:2.2 关键算法分析代码描述:1.构造函数template < class T >void BiTree<T>::Creat(BiNode<T>*&R, T data[], int i,int n)//i表示位置,从1开始,n表示数组长度{if (i <= n&&data[i - 1]){R = new BiNode < T > ;//创建根节点R->data = data[i - 1];Creat(R->LChild, data, 2 * i, n);//创建左子树Creat(R->RChild, data, 2 * i + 1, n);//创建右子树}else R = NULL;}template<class T>BiTree<T>::BiTree(T data[], int n){Creat(Root, data, 1, n);//利用递归循环构造}2.前序遍历//前序遍历,递归template<class T>void BiTree<T>::PreOrder(BiNode<T>*R)//前序遍历,递归//R都是源自于一开始构造所产生的根节点//根->左->右{if (R != NULL){cout << R->data<<" ";//访问结点PreOrder(R->LChild);//遍历左子树PreOrder(R->RChild);//遍历右子树}}//前序遍历,非递归template<class T>void BiTree<T>::PreOrderNormal(BiNode<T>*R)//用栈模板进行非递归操作{stack<BiNode<T>*> s;//结构栈BiNode<T>* p = R;//从根结点开始循环while (p != NULL || !s.empty()){while (p != NULL){cout << p->data << " ";s.push(p);p = p->LChild;//先压栈,再更改指针域}if (!s.empty())//检验栈是否为空,栈为空后,遍历结束{p = s.top();s.pop();p = p->RChild;}}}3.中序遍历//中序遍历,递归template<class T>void BiTree<T>::InOrder(BiNode<T>*R)//左->根->右//递归,中序遍历{if (R != NULL){InOrder(R->LChild);//遍历左子树cout << R->data<<" ";//访问节点InOrder(R->RChild);//遍历右子树}}4.后序遍历//后序遍历,递归template<class T>void BiTree<T>::PostOrder(BiNode<T>*R)//递归,后序遍历//左->右->根{if (R != NULL){PostOrder(R->LChild);//遍历左子树PostOrder(R->RChild);//遍历右子树cout << R->data<<" ";//访问节点}}时间复杂度:O(n)5.层序遍历template<class T>void BiTree<T>::LevelOrder(BiNode<T>*R)//层序遍历{queue<BiNode<T>*> q;BiNode<T>* p = R;//从根结点开始循环if(p!=NULL) q.push(p);while (!q.empty()){p = q.front();cout << p->data<<" ";q.pop();if (p->LChild != NULL) q.push(p->LChild);if (p->RChild != NULL) q.push(p->RChild);}}6.析构函数//析构函数template<class T>void BiTree<T>::Release(BiNode<T>*R){if (R != NULL){Release(R->LChild);//释放左子树Release(R->RChild);//释放右子树delete R;//释放根节点}}template<class T>BiTree<T>::~BiTree(){Release(Root);//释放二叉树}7.求二叉树深度template<class T>int BiTree<T>::Depth(BiNode<T>*R)//输出二叉树的深度{if (R == NULL) return 0;else{int m = Depth(R->LChild);int n = Depth(R->RChild);return m >= n ? m + 1:n + 1;}}时间复杂度:O(n)8.求路径template<class T>bool BiTree<T>::Findpath(BiNode<T>*R, T s)//找出指定元素到根节点的路径{if (R == NULL){return false;}else{if (R->data == s)//当前元素等于e,输出该节点{cout << R->data<<" ";return true;}else if (Findpath(R->LChild, s))//经过该结点的左孩子能到达e,输出该结点{cout << R->data<<" ";return true;}else if (Findpath(R->RChild, s))//经过该结点的右孩子能到达e,输出该结点{cout << R->data << " ";return true;}elsereturn false;}}template<class T>void BiTree<T>::Detect(BiNode<T>*R, T s){if (!(Findpath(R, s))){throw"输入元素有误!";}}3. 程序运行结果主函数流程图:测试截图:初始化二叉树,菜单创建执行功能:4. 总结.调试时出现了一些问题如:异常抛出的处理,书中并未很好的提及异常处理,通过查阅资料,选择用try catch 函数对解决。
数据结构二叉排序树
数据结构二叉排序树二叉排序树(Binary Search Tree)是一种特殊的二叉树,又称二叉查找树或二叉搜索树。
它的左子树上所有结点的值均小于它的根结点的值,右子树上所有结点的值均大于它的根结点的值。
并且左、右子树也分别是二叉排序树。
二叉排序树的实现,通常使用链式存储结构。
每个节点包含三个数据成员:key,left和right。
key为节点的关键字,left和right分别表示左右孩子节点的指针。
二叉排序树的查找过程是从根节点开始,比较要查找的关键字和根节点的关键字的大小,如果相等,则找到所需节点;如果比根节点小,则在左子树中继续查找;如果比根节点大,则在右子树中继续查找,直到找到所需节点或者指针为空。
二叉排序树的插入过程是先进行查找操作,找到插入的位置后,在该位置插入新节点。
插入一个新的节点会改变原有的结构,需要不断地调整二叉排序树,使之重新满足二叉排序树定义的性质。
二叉排序树的删除过程比较复杂,需要考虑多种情况。
如果要删除的节点是叶子节点,直接删除即可;如果要删除的节点只有一个子节点,将其子节点替换成该节点即可;如果要删除的节点有两个子节点,需要找到其右子树中的最小节点或者左子树中的最大节点作为替代节点。
二叉排序树的优缺点:优点:1. 查找、插入、删除元素的操作复杂度均为O(log n),比线性查找的复杂度O(n)要快。
2. 适用于查找、排序、统计和检索大量元素的应用场景,例如字典、电话簿等。
3. 在存储元素的过程中,可以任意添加或删除元素,不会导致其他元素的位序改变。
4. 这种数据结构利用了树的优点,非常适合用于内存有限的情况下。
缺点:1. 当元素的排序规则不合理时,二叉排序树可能导致树的深度较大,从而影响操作效率。
2. 二叉排序树的构造过程是顺序插入的,可能会造成树的不平衡,进而影响操作效率。
3. 二叉排序树对于相同元素的重复插入会导致树的深度增大,从而影响操作效率。
总结:二叉排序树是一种优秀的数据结构,用于排序和查找元素的操作。
北邮数据结构实验报告
北邮数据结构实验报告北邮数据结构实验报告一、引言数据结构是计算机科学中的重要基础知识,对于计算机程序的设计和性能优化起着至关重要的作用。
本报告旨在总结北邮数据结构实验的相关内容,包括实验目的、实验设计、实验过程和实验结果等。
二、实验目的本次实验旨在通过实践操作,加深对数据结构的理解和应用能力。
具体目的如下:1. 掌握线性表、栈和队列等基本数据结构的实现方法;2. 熟悉二叉树、图等非线性数据结构的构建和遍历算法;3. 学会使用递归和非递归算法解决实际问题;4. 培养编程实践能力和团队合作意识。
三、实验设计本次实验包括以下几个部分:1. 线性表实验:设计一个线性表类,实现线性表的基本操作,如插入、删除和查找等。
通过实验,了解线性表的顺序存储和链式存储结构的特点和应用场景。
2. 栈和队列实验:设计栈和队列类,实现栈和队列的基本操作,如入栈、出栈、入队和出队等。
通过实验,掌握栈和队列的应用,如括号匹配、迷宫求解等。
3. 二叉树实验:设计二叉树类,实现二叉树的创建、遍历和查找等操作。
通过实验,熟悉二叉树的前序、中序和后序遍历算法,并了解二叉树的应用,如表达式求值等。
4. 图实验:设计图类,实现图的创建、遍历和最短路径等操作。
通过实验,掌握图的邻接矩阵和邻接表表示方法,并了解图的深度优先搜索和广度优先搜索算法。
四、实验过程1. 线性表实验:根据实验要求,首先选择线性表的存储结构,然后设计线性表类,实现插入、删除和查找等基本操作。
在实验过程中,遇到了一些问题,如边界条件的处理和内存管理等,通过团队合作,最终解决了这些问题。
2. 栈和队列实验:根据实验要求,设计栈和队列类,实现入栈、出栈、入队和出队等基本操作。
在实验过程中,我们发现了栈和队列在实际应用中的重要性,如括号匹配和迷宫求解等,通过实验加深了对栈和队列的理解。
3. 二叉树实验:根据实验要求,设计二叉树类,实现二叉树的创建、遍历和查找等操作。
在实验过程中,我们发现了二叉树在表达式求值和排序等方面的应用,通过实验加深了对二叉树的理解。
《数据结构》综合性实验-平衡二叉排序树实验指导
《数据结构》综合性、设计性实验指导一、实验题目实现平衡二叉排序树的各种算法二、实验内容用函数实现如下平衡二叉排序树算法:(1)插入新结点(2)前序、中序、后序遍历二叉树(递归)(3)前序、中序、后序遍历的非递归算法(4)层次遍历二叉树(5)在二叉树中查找给定关键字(函数返回值为成功1,失败0)(6)交换各结点的左右子树(7)求二叉树的深度(8)叶子结点数(9)删除某结点三、实验目的(1)掌握递归算法(2)掌握堆栈算法(3)掌握队列算法(4)掌握树型查找(5)提高对树型结构的综合应用能力四、实验要求(1)独立完成实验内容(2)算法设计符合程序书写规范, 要求有注释、函数功能及参数说明(3)实验报告的封面见附表A(4)实验报告参考附表《实验报告书写规范》书写(5)课程结束时要求在指定时间内上交实验的电子文档附件A: 实验报告封面华南农业大学信息学院综合性、设计性实验教师签名: 杨秋妹附件B实验报告规范一、实习报告的开头应给出题目、班级、姓名、学号和完成日期, 并包括以下内容:二、分析题目要求1)陈述说明程序设计的任务, 强调的是程序要做什么并明确规定:2)各个函数命名, 包含的参数, 返回值类型3)输入的形式和输入值的范围4)输出的形式5)程序所能达到的功能三、解题思路对于要实现的各个操作, 分别说明其应如何求解, 用伪码形式描述其求解过程, 求解过程中用到的数据结构。
四、调试分析1)调试过程中遇到的问题是如何解决的以及对设计与实现的回顾讨论和分析2)使用的测试数据(要求多组)3)算法的效率分析和改进设想4)经验和体会五、附录带注释的源程序。
注意: 1.只交电子版2.每个同学的资料存放在以学号姓名为文件夹名的目录下, 有学习委员收齐后统一交给任课教师。
数据结构实验报告二叉树
数据结构实验报告二叉树二叉树是一种重要的数据结构,广泛应用于计算机科学和算法设计中。
在本次实验中,我们通过实际编程实践,深入理解了二叉树的基本概念、性质和操作。
一、二叉树的定义和基本性质二叉树是一种特殊的树结构,每个节点最多有两个子节点。
它具有以下基本性质:1. 根节点:二叉树的顶部节点称为根节点,它没有父节点。
2. 子节点:每个节点最多有两个子节点,分别称为左子节点和右子节点。
3. 叶节点:没有子节点的节点称为叶节点。
4. 深度:从根节点到某个节点的路径长度称为该节点的深度。
5. 高度:从某个节点到其叶节点的最长路径长度称为该节点的高度。
6. 层次遍历:按照从上到下、从左到右的顺序遍历二叉树的节点。
二、二叉树的实现在本次实验中,我们使用C++语言实现了二叉树的基本操作,包括创建二叉树、插入节点、删除节点、查找节点等。
通过这些操作,我们可以方便地对二叉树进行增删改查。
三、二叉树的遍历二叉树的遍历是指按照某种顺序访问二叉树的所有节点。
常用的遍历方式有三种:前序遍历、中序遍历和后序遍历。
1. 前序遍历:先访问根节点,然后依次递归遍历左子树和右子树。
2. 中序遍历:先递归遍历左子树,然后访问根节点,最后递归遍历右子树。
3. 后序遍历:先递归遍历左子树,然后递归遍历右子树,最后访问根节点。
四、二叉树的应用二叉树在计算机科学和算法设计中有广泛的应用。
以下是一些常见的应用场景:1. 二叉搜索树:二叉搜索树是一种特殊的二叉树,它的左子树的值都小于根节点的值,右子树的值都大于根节点的值。
它可以高效地支持插入、删除和查找操作,常用于有序数据的存储和检索。
2. 堆:堆是一种特殊的二叉树,它的每个节点的值都大于(或小于)其子节点的值。
堆常用于实现优先队列等数据结构。
3. 表达式树:表达式树是一种用二叉树表示数学表达式的方法。
通过对表达式树的遍历,可以实现对数学表达式的计算。
4. 平衡树:平衡树是一种特殊的二叉树,它的左右子树的高度差不超过1。
北邮数据结构实验报告3二叉树含源码
数据结构实验报告实验名称:实验三——树题目一学生姓名:申宇飞班级:2012211103班内序号:03学号:2012210064日期:2013年12月3日1.实验要求掌握二叉树基本操作的实现方法根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。
二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2. 程序分析2.1 存储结构采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包含三个元素,分别是一个T类型的数据域data,一个指向T类型的指针左孩子,一个指向T 类型的指针右孩子,示意图如图所示。
采用了队列的存储结构。
示意图如图所示:对于二叉树中每个结点的data 域的赋值,我们事先把这些data 储存在一个数组中,通过对数组元素的调用事先对二叉树中每个结点的data 域的赋值。
2.2 关键算法分析 一:二叉树的建立: A . 自然语言描述:1首先判断调用的数组是否为空,如果为空,直接将一个已经初始化好的根节点置为空。
2 如果该数组不为空,则把调用的数组的第一个元素的赋给根节点的data 域。
3 采用递归的思想,分别将根节点的左右孩子作为根节点,递归调用该函数。
完成对左右子树的赋值。
B . 代码详细分析:template <class T> void BiTree<T>::Create(Node<T> *&R,T* buf,int i) {if (buf[i-1]==0) R = NULL; else {R=new Node<T>; R->data = buf[i-1];Create(R->lch, buf, 2*i); Create(R->rch, buf, 2*i+1); }lchdata rchlchdata rchlchdata rchlchdata rchlchdata rchlchdata rchlch data rchA[2*i]A[2*i+1] lch data rch lch data rch二:前序遍历二叉树:A. 自然语言描述:1:建立栈2:判断该栈是否为空并且根节点是否为空指针3:如果根节点不是空指针,则输出它的data域,并且是它入栈4:入栈后将根节点指针指向它的左孩子5:如果根节点是空指针6:则根节点出栈,并且指向根节点的指针指向它的右孩子B.代码详细分析:template <class T> void BiTree<T>::Preorder(Node<T> *R){Stack<Node<T>*> S;while(!S.IsEmpty() || (R!=NULL)){if (R!=NULL){Print(R->data);S.Push(R);R=R->lch;}else{R=S.Pop();R=R->rch;}}}三:中序遍历二叉树:A.自然语言描述:1:建立栈2:判断该栈是否为空并且根节点是否为空指针3:如果根节点不是空指针,将它入栈4:入栈后将根节点指针指向它的左孩子5:如果根节点是空指针6:则根节点出栈,输出该节点的data域,并且指向根节点的指针指向它的右孩子B. 代码详细分析:template <class T> void BiTree<T>::Inorder(Node<T> *R){Stack<Node<T>*> S;while(!S.IsEmpty() || (R!=NULL)){if (R!=NULL){S.Push(R);R=R->lch;}else{R=S.Pop();Print(R->data);R=R->rch;}}}四:后序遍历二叉树:A.自然语言描述:1:判断根节点是否为空2:如果根节点不为空3:递归调用后续遍历函数,函数的参数改为根节点的左孩子 4:递归调用后续遍历函数,函数的参数改为根节点的右孩子 5:输出根节点的data域B.代码详细分析:template <class T> void BiTree<T>::Postorder(Node<T> *R) {if (R!=NULL) {Postorder(R->lch);Postorder(R->rch);Print(R->data);}}}}123五:层序遍历二叉树:A.自然语言描述:1:判断根节点是否为空2:如果根节点不为空3:输出根节点的data域4:递归调用层续遍历函数,函数的参数改为根节点的左孩子5:递归调用层序遍历函数,函数的参数改为跟结点的右孩子B.代码详细分析:template <class T> void BiTree<T>::Levelorder(Node<T> *R){Queue<Node<T>*> Q;while(!Q.IsEmpty() || (R!=NULL)){if (R!=NULL){Print(R->data);Q.EnQueue(R->lch);Q.EnQueue(R->rch);}R=Q.DelQueue();}}}123六:求二叉树的深度:A.自然语言描述:1:判断根节点是否为空,如果根节点为空,返回02:如果根节点不为空但是根节点的左右孩子同时为空,返回13:如果以上两个条件都不成立4:递归调用求二叉树的深度,函数的参数改为根节点的左孩子,并且深度初始化为1 5:递归调用求二叉树的深度,函数的参数改为跟结点的右孩子,并且深度初始化为0 6:返回4与5步中得出深度较大的那个数作为二叉树的深度数B.代码详细分析:template <class T> int BiTree<T>::GetDepth(Node<T> *R,int d){if (R==NULL) return d;if ((R->lch==NULL) && (R->rch==NULL))return d+1;else{int m = GetDepth(R->lch,d+1); int n = GetDepth(R->rch,d+1); return n>m? n:m; } }七:二叉树的销毁 A.自然语言描述:1:判断根节点是否为空 2:如果根节点不为空3:递归调用二叉树的销毁函数,参数改为根节点的左孩子 4:递归调用二叉树的销毁函数,参数改为根节点的右孩子 5:释放根节点指向的内存 B.代码详细分析:template <class T> void BiTree<T>::Destroy(Node<T> *R) {if (R!=NULL) { Destroy(R->lch); Destroy(R->rch); delete R; } }}:123八:求二叉树的叶子结点数: A.自然语言描述:1:判断根节点是否为空,如果为空,返回02:如果根节点不为空,切根节点的左右孩子同时为空,返回13:递归调用求二叉树的叶子节点数函数,参数改为根节点的左孩子 4:递归调用求二叉树的叶子结点数函数,参数改为根节点的右孩子 5:返回根节点的左右子树的叶子结点数之和 B.代码详细分析:template <class T> int BiTree<T>::LeafNodeCount(Node<T> *R) {if (R==NULL) return 0;if ((R->lch==NULL) && (R->rch==NULL)) return 1; else {int n=LeafNodeCount(R->lch); int m=LeafNodeCount(R->rch); return m+n; } }九:求二叉树的结点数: A.自然语言描述:} }123}1231:判断根节点是否为空,如果为空,返回02:如果根节点不为空3:递归调用求二叉树的结点数的函数,参数改为根节点的左孩子4:递归调用求二叉树的结点数的函数,参数改为根节点的右孩子5:返回根节点的左右字数的结点数之和B.代码详细分析:template <class T> int BiTree<T>::NodeCount(Node<T> *R){if (R==NULL) return 0;else{int m=NodeCount(R->lch);}}int n=NodeCount(R->rch); return m+n+1;}1232.3 其他对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。
数据结构 二叉排序树
数据结构二叉排序树数据结构二叉排序树1. 概述二叉排序树(Binary Search Tree,简称BST)是一种基于二叉树的数据结构,具有以下特点:- 每个节点最多只有两个子节点。
- 对于树中的任意节点,其左子树上所有节点的值都小于该节点的值,右子树上所有节点的值都大于该节点的值。
- 中序遍历二叉排序树得到的结果是一个有序序列。
2. 二叉排序树的操作2.1 插入二叉排序树的插入操作是将一个新的节点插入到二叉排序树中的合适位置,使得二叉排序树仍然满足以上特点。
插入操作的具体步骤如下:1. 若二叉排序树为空树,则将新节点作为根节点插入即可。
2. 若二叉排序树不为空,比较新节点的值与当前节点的值的大小关系:- 若新节点的值小于当前节点的值,则继续在当前节点的左子树中进行插入操作。
- 若新节点的值大于当前节点的值,则继续在当前节点的右子树中进行插入操作。
2.2 删除二叉排序树的删除操作是将指定节点从二叉排序树中删除,并保持二叉排序树的特性不变。
删除操作的具体步骤如下:1. 若待删除节点为叶子节点,则直接将其父节点指向该节点的指针置为null。
2. 若待删除节点只有左子树或只有右子树,则将其父节点指向该节点的指针直接指向该节点的子节点。
3. 若待删除节点既有左子树又有右子树,则需要找到其右子树中的最小节点(或左子树中的最大节点)来替代待删除节点。
具体步骤如下:- 先找到待删除节点右子树中的最小节点(即右子树中最左下的节点),或者左子树中的最大节点。
- 将该最小(或最大)节点的值复制到待删除节点。
- 将最小(或最大)节点从右子树(或左子树)中删除。
2.3 查找二叉排序树的查找操作是在树中寻找具有指定值的节点。
查找操作的具体步骤如下:1. 从根节点开始,将待查找的值与当前节点的值进行比较。
2. 若待查找的值等于当前节点的值,则返回该节点。
3. 若待查找的值小于当前节点的值,则继续在当前节点的左子树中进行查找操作。
北邮数据结构实验报告
二、试验内容:
用编码。
利用二叉树结构实现哈夫曼编/解码器
2. 程序分析
1.初始化:能够对输入的任意长度的字符串 s 进行统计,统计每
2.1 存储结构
个字符的频度,并建立哈夫曼树。
二叉树
2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字
魏
第1页共3页
本文格式为 Word 版,下载可任意编辑
template class BiTree { public: BiTree(); //构造函数,其前序序列由键盘输入 ~BiTree(void); //析构函数 BiNode* Getroot(); //获得指向根结点的指针 protected: BiNode *root; //指向根结点的头指针 }; //声明类 BiTree 及定义结构 BiNode Data: 二叉树是由一个根结点和两棵互不相交的左右子树构成
魏
第2页共3页
本文格式为 Word 版,下载可任意编辑
{ char data; //编码表中的字符 char code[100]; //该字符对应的编码 }; 待编码字符串由键盘输入,输入时用链表存储,链表节点为 struct Node { char character; //输入的字符 unsigned int count;//该字符的权值 bool used; //建立树的时候该字符是否使用过 Node* next; //保存下一个节点的地址 }; 示意图:
本文格式为 Word 版,下载可任意编辑
北邮数据结构实验报告
符的编码输出。 3.编码:依据编码表对输入的字符串进行编码,并将编码后的
字符串输出。
2021 级数据结构试验报告
4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,
北邮数据结构实验—二叉排序树
数据结构实验报告实验名称:______二叉排序树___________ 学生姓名:____________________班级:_______________班内序号:_______________________学号:________________日期:________________1.实验要求根据二叉排序树的抽象数据类型的定义,使用二叉链表实现一个二叉排序树。
二叉排序树的基本功能:1.二叉排序树的建立2.二叉排序树的查找3.二叉排序树的插入4.二叉排序树的删除5.二叉排序树的销毁6.其他:自定义操作编写测试main()函数测试二叉排序树的正确性2. 程序分析2.1 存储结构二叉链表2.2 程序流程(或程序结构、或类关系图等表明程序构成的内容,一般为流程图等)2.2.1.2.2.2.伪代码1.从文件读取待建树元素2.建树,若待插入元素比根节点小,向左子树前进并重复比较左子树根节点,若待插入元素比根节点大,向右子树前进并重复比较右子树根节点,直至找到空节点则插入该元素,不断插入直至不剩下元素。
3.用户选择操作。
4.若用户选择查找,则现由用户输入待查找数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等,则输出节点情况。
5.若用户选择插入,则现由用户输入待插入数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至到空节点,则插入该元素。
6.若用户选择删除,则现由用户输入待删除数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等;1).若该节点为叶子节点,则直接删除;2).若该节点无左子树,则其双亲节点直接与其右子树根节点连接,再删除该节点;3).若该节点有左子树,则其左子树的最右节点数值直接覆盖该节点数值,再删除最后节点。
7.若用户选择销毁,则不断执行删除操作直至不剩余节点。
8.若用户选择退出,则程序结束。
2.3 关键算法分析关键代码即删除操作,代码如下:void Delete(BiNode* &R){BiNode* q=new BiNode;BiNode *s=new BiNode;if(R->lch==NULL){q=R;R=R->rch;delete q;}else if(R->rch==NULL){q=R;R=R->lch;delete q;}else{q=R;s=R->lch;while(s->rch!=NULL){q=s;s=s->rch;}R->data=s->data;if(q!=R)q->rch=s->lch;elseR->lch=s->lch;delete s;}}void Deletedata(BiNode* &R, int key){if(R==NULL) return;if(R->data==key) Delete(R);else if(R->data>key) Deletedata(R->lch,key);else Deletedata(R->rch,key);}首先先要定位到要删除的节点,不断递归调用deletedata这个函数,找到数值与需要删除节点的数值相等的节点时,调用delete这个函数。
数据结构实验报告-二叉排序树的插入和检索
二叉排序树的插入和检索一、实验目的(对应的中级实验的实验目的)二叉排序树的插入和检索(1)实现二叉排序树的检索,若成功,记录检索的位置信息,若不成功,记录父结点的位置信息。
(2)调用检索算法实现插入,并输出插入后的二叉排序树。
(3)实现删除算法,删除后仍然满足二叉排序树的定义,并输出删除后的结果。
要求:用链式存储实现字典结构。
提示:对二叉排序树进行中根序遍历时,获得的是排序序列。
算法思想(1)创建二叉排序树算法:如果任一结点的左子树非空,则左子树中的所有结点的关键码都小于根结点的关键码;如果任一结点的右子树非空,则右子树中的所有结点的关键码都大于根结点的关键码。
(2)二叉排序树的检索二叉排序树的检索时,若成功,记录检索的位置信息(显示检索成功的信息),若不成功,记录父结点的位置信息(显示检索不成功的信息)。
(3)二叉排序树的插入插入后的二叉树仍满足二叉排序树的定义,插入新结点的方法:1.如果二叉排序树为空,则新结点作为根结点。
2.如果二叉排序树非空,则将新结点的关键码与根结点的关键码比较,若相等表示该结点已在二叉排序树中;若小于根结点的关键码,则将新结点插入到根结点的左子树中;否则,插入到右子树中。
3.子树中的插入过程和树中的插入过程相同,如此进行下去,直到找到该结点,或者直到左或右子树非空二叉树,新结点插入成为叶子结点为止。
(4)二叉排序树的删除删除结点后的二叉树仍满足二叉排序树的定义;第一种方法:1.如果被删除结点p没有左子树,则用p的右子女代替p即可;2.否则,在p的左子树中,找出关键码最大的一个结点r (r 处于p的左子树中最右下角的位置,r一定无右子女),将r的右指针指向p的右子女,用p的左子女代替p结点。
第二种方法:1.如果被删除结点p没有左子树,则用p的右子女代替p即可;2.否则,在p的左子树中,找出关键码最大的一个结点r,用结点r代替被删除的结点p,p原来的左右子女,并且用原来r的左子女代替原来的结点r。
二叉排序树实验报告
二叉排序树实验报告二叉排序树实验报告一、引言二叉排序树,也被称为二叉搜索树,是一种常见的数据结构,它具有快速的查找和插入操作的特点。
在本次实验中,我们将探索二叉排序树的原理和实现,并通过实际操作来验证其性能和效果。
二、实验目的本次实验的目的是通过实际操作,深入理解二叉排序树的原理和实现,并通过对比不同操作的时间复杂度,评估其性能和效果。
三、实验过程1. 实验环境的搭建在开始实验之前,我们需要搭建一个合适的实验环境。
我们可以选择使用C++或者其他编程语言来实现二叉排序树。
在本次实验中,我们选择使用C++来实现。
2. 二叉排序树的实现首先,我们需要定义一个二叉排序树的数据结构。
这个数据结构包含一个根节点,每个节点包含一个值和两个指针,分别指向左子树和右子树。
通过递归的方式,我们可以实现二叉排序树的插入、删除和查找操作。
3. 实验数据的准备为了验证二叉排序树的性能和效果,我们需要准备一组实验数据。
这组数据可以是随机生成的整数,也可以是具有特定规律的数据。
我们可以选择不同规模的数据集来进行实验,以评估二叉排序树在不同情况下的表现。
4. 实验操作的执行通过实验数据的准备,我们可以开始执行实验操作。
首先,我们将数据依次插入到二叉排序树中,并记录下插入操作的时间。
然后,我们可以执行查找操作,查找树中是否包含某个特定的值,并记录下查找操作的时间。
最后,我们可以执行删除操作,删除树中的某个节点,并记录下删除操作的时间。
5. 实验结果的分析通过实验操作的执行,我们可以得到一组实验结果。
我们可以通过对比不同操作的时间复杂度,来评估二叉排序树的性能和效果。
同时,我们还可以观察实验结果中树的结构,以验证二叉排序树的正确性。
四、实验结果与讨论通过实验操作的执行,我们得到了一组实验结果。
我们可以观察到,随着数据规模的增加,插入、查找和删除操作的时间逐渐增加。
这是因为二叉排序树的操作时间复杂度与树的高度相关,当树的高度增加时,操作的时间复杂度也会增加。
国家开放大学《数据结构》课程实验报告(实验4——二叉树)参考答案
(实验4二叉树)
学生姓名
学 号
班 级
指导老师
实验名称
实验成绩
实验报告
实ቤተ መጻሕፍቲ ባይዱ
验
概
述
实验目的:
(1)根据数组tree,建立与该二叉树对应的链式存储结构。
(2)对该二叉树采用中序遍历法显示遍历结果。
实验要求:
(1)在主函数中,通过键盘输入建立设定的完全二叉树的顺序存储结构。
(2)设计子函数,其功能为将顺序结构的二叉树转化为链式结构。
(2)中序遍历采用递归算法,即中序遍历左子树、访问根结点、中序遍历右子树。
实
验
内
容
程序代码:
/*实验3.1二叉树的顺序存储结构和链式存储结构*/
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 20
/*二叉树链式存储结构结点定义*/
typedef struct BTreeNode
指
导
教
师
评
语
指导教师 日期
(3)设计子函数,其功能为对给定二叉树进行中序遍历,显示遍历结果。
(4)通过实例判断算法和相应程序的正确性。
实验基本原理:
(1)顺序存储的二叉树转化为链式存储结构,采用递归算法,递归函数的形式为Creab(tree,n,i,b),其中形参:tree为顺序存储二叉树的数组,n为二叉树的结点数,i是二叉树某结点在数组tree中的下标(初始值为1),b为要建立的链式存储二叉树结点指针。转化时,首先建立*b结点,将tree[i]的值赋给*b的数据域,再调用递归函数分别构造左子树和右子树。
数据结构实验-二叉排序树应用实验报告(内容清晰)
数据结构实验-二叉排序树应用实验报告(内容清晰)实验报告实验课程:数据结构实验项目:实验四二叉排序树应用专业:计算机科学与技术班级:姓名:学号:指导教师:目录一、问题定义及需求分析(1)问题描述(2)实验任务(3)需求分析二、概要设计:(1)抽象数据类型定义(2)主程序流程(3) 模块关系三、详细设计(1)数据类型及存储结构(2)模块设计四、调试分析(1)调试分析(2)算法时空分析(3)经验体会五、使用说明(1)程序使用说明六、测试结果(1)运行测试结果截图七、附录(1)源代码一、问题定义及需求分析(1)实验目的二叉排序树应用问题描述互联网域名系统是一个典型的树形层次结构。
从根节点往下的第一层是顶层域,如cn、com等,最底层(第四层)是叶子结点,如www等。
因此,域名搜索可以构造树的结构完成;(2)实验任务设计基于二叉排序树的搜索互联网域名的程序。
(3)需求分析:1)采用二叉树的二叉链表存储结构。
2)完成二叉排序树的创建、插入、删除、查询操作。
3)可以考虑两棵二叉排序树的合并。
二、概要设计:(1)抽象数据类型定义:程序中定义了二叉排序树的节点类型;由数据域和左右孩子指针构成;指针类型为该节点类型,指向该类型的节点形成二叉排序树;数据域是由字符数组构成,用于存储节点数据信息。
(2)主程序流程:输入域名拆分域名并完成二叉排序树的创建调用功能函数进入功能菜单选择执行不同的操作(查找、插入、删除) 操作完毕后可选择返回功能函数继续执行操作或者结束程序(3)模块间的调用关系:创建二叉排序树功能函数查找插入删除选择结束三、详细设计采用二叉链表存储结构的二叉排序树的定义如下:typedef struct BiTNode{ElemType data[30]; //定义数据域类型为字符数组struct BiTNode *lchild, *rchild; //定义左右孩子节点指针}BiTNode, *BiTree;模块1-查找树中是否有待插入节点算法如下:int SearchBST(BiTree T, char *key, BiTree f, BiTree *p){if (!T) /* 查找不成功*/{*p = f;return 0;}else if(strcmp(key,T->data)==0) /* 查找成功*/{*p = T;return 1;}else if (strcmp(key,T->data)<0)return SearchBST(T->lchild, key, T, p); /* 若该节点小于当前节点,则在左子树中继续查找*/elsereturn SearchBST(T->rchild, key, T, p); /* 否则在右子树中继续查找*/ }模块2-插入节点算法如下:int InsertBST(BiTree *T, char *key){BiTree p,s;if (!SearchBST(*T, key, NULL, &p)) /* 查找不成功*/ {s = (BiTNode*)malloc(sizeof(BiTNode));strcpy(s->data, key);s->lchild = s->rchild = NULL;。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验报告实验名称:______二叉排序树___________ 学生姓名:____________________班级:_______________班内序号:_______________________学号:________________日期:________________1.实验要求根据二叉排序树的抽象数据类型的定义,使用二叉链表实现一个二叉排序树。
二叉排序树的基本功能:1.二叉排序树的建立2.二叉排序树的查找3.二叉排序树的插入4.二叉排序树的删除5.二叉排序树的销毁6.其他:自定义操作编写测试main()函数测试二叉排序树的正确性2. 程序分析2.1 存储结构二叉链表2.2 程序流程(或程序结构、或类关系图等表明程序构成的内容,一般为流程图等)2.2.1.2.2.2.伪代码1.从文件读取待建树元素2.建树,若待插入元素比根节点小,向左子树前进并重复比较左子树根节点,若待插入元素比根节点大,向右子树前进并重复比较右子树根节点,直至找到空节点则插入该元素,不断插入直至不剩下元素。
3.用户选择操作。
4.若用户选择查找,则现由用户输入待查找数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等,则输出节点情况。
5.若用户选择插入,则现由用户输入待插入数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至到空节点,则插入该元素。
6.若用户选择删除,则现由用户输入待删除数值。
从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等;1).若该节点为叶子节点,则直接删除;2).若该节点无左子树,则其双亲节点直接与其右子树根节点连接,再删除该节点;3).若该节点有左子树,则其左子树的最右节点数值直接覆盖该节点数值,再删除最后节点。
7.若用户选择销毁,则不断执行删除操作直至不剩余节点。
8.若用户选择退出,则程序结束。
2.3 关键算法分析关键代码即删除操作,代码如下:void Delete(BiNode* &R){BiNode* q=new BiNode;BiNode *s=new BiNode;if(R->lch==NULL){q=R;R=R->rch;delete q;}else if(R->rch==NULL){q=R;R=R->lch;delete q;}else{q=R;s=R->lch;while(s->rch!=NULL){q=s;s=s->rch;}R->data=s->data;if(q!=R)q->rch=s->lch;elseR->lch=s->lch;delete s;}}void Deletedata(BiNode* &R, int key){if(R==NULL) return;if(R->data==key) Delete(R);else if(R->data>key) Deletedata(R->lch,key);else Deletedata(R->rch,key);}首先先要定位到要删除的节点,不断递归调用deletedata这个函数,找到数值与需要删除节点的数值相等的节点时,调用delete这个函数。
删除节点时需要分析三种情况。
1).若该节点为叶子节点,则直接删除;2).若该节点无左子树,则其双亲节点直接与其右子树根节点连接,再删除该节点;3).若该节点有左子树,则其左子树的最右节点数值直接覆盖该节点数值,再删除最后节点。
算法时间复杂度:O(n^2)2.4 其他特殊情况处理:若文件里元素为空,不存在任何元素,则无法完成建树,选择查找操作时也会提示无元素;另外,若查找不存在的元素是,最后查找到空节点也会提示无此元素。
3.程序运行结果分析4.总结4.1实验的难点和关键点本实验的难点和关键点主要在删除元素上,为了保持二叉排序树的有序性。
删除特定节点是要分三种情况讨论1).若该节点为叶子节点,则直接删除;2).若该节点无左子树,则其双亲节点直接与其右子树根节点连接,再删除该节点;3).若该节点有左子树,则其左子树的最右节点数值直接覆盖该节点数值,再删除最后节点。
4.2心得体会通过这次试验让我进一步对树的应用有了进一步的了解,同时对查找这种基本数据操作有了较深刻的认识.同时在二叉排序树的删除操作的代码编写时,让我明白了不同情况的不同处理方式。
养成了更严谨的编写代码的思维方式。
附:程序代码#include<iostream>#include<fstream>using namespace std;class BiNode{public:int data;BiNode* lch;BiNode* rch;BiNode():lch(NULL),rch(NULL){};};BiNode* Search(BiNode* R,int key){ if(R==NULL) {cout<<"无查询结果"<<endl;return NULL;}if(R->data==key) return R;if(R->data<key) return Search(R->rch,key);if(R->data>key) return Search(R->lch,key);}void Insert(BiNode* &R,BiNode* S){if(R==NULL) R=S;if(R->data<S->data) Insert(R->rch,S);if(R->data>S->data) Insert(R->lch,S);}BiNode* Create(int data[],int n){BiNode* R=new BiNode;R=NULL;for(int i=0;i<n;i++){BiNode* Q=new BiNode;Q->data=data[i];Insert(R,Q);}return R;}void Delete(BiNode* &R){BiNode* q=new BiNode;BiNode *s=new BiNode;if(R->lch==NULL){q=R;R=R->rch;delete q;}else if(R->rch==NULL){q=R;R=R->lch;delete q;}else{q=R;s=R->lch;while(s->rch!=NULL){q=s;s=s->rch;}R->data=s->data;if(q!=R)q->rch=s->lch;elseR->lch=s->lch;delete s;}}void Deletedata(BiNode* &R, int key){if(R==NULL) return;if(R->data==key) Delete(R);else if(R->data>key) Deletedata(R->lch,key);else Deletedata(R->rch,key);}void Deleteall(BiNode* &R,int data[],int n){for(int i=0;i<n;i++){Deletedata(R,data[i]);}}void main(){int data[200];BiNode *Root;Root=NULL;ifstream ifile("D://TEST//data.txt");int i=0,n=0;cout<<"从文件读入数据如下:"<<endl;while(ifile>>data[i]){cout<<data[i]<<" ";i++;n++;}Root=Create(data,n);while(1){cout<<"\n请输入进行的操作:\n1.查找\n2.插入\n3.删除\n4.销毁\n5.退出\n"; int choice;cin>>choice;while(choice!=1&&choice!=2&&choice!=3&&choice!=4&&choice!=5){ cout<<"无该选项,请重新输入";cin>>choice;}switch(choice){case 1:{cout<<"请输入查找的数据"<<endl;int n;int i;cin>>n;BiNode* R;R=Search(Root,n);if(R->lch!=NULL){cout<<"该数据节点左孩子数据为"<<R->lch->data<<endl;}if(R->rch!=NULL){cout<<"该数据节点右孩子数据为"<<R->rch->data<<endl;}if(R->lch==NULL&&R->rch==NULL){cout<<"该数据节点为叶子节点";}break;}case 2:{cout<<"请输入插入数据"<<endl;int t;cin>>t;BiNode* w=new BiNode;w->data=t;Insert(Root,w);cout<<"插入成功"<<endl;cout<<"目前关键码为:";for(int i=0;i<n;i++){cout<<data[i]<<" ";}cout<<t<<" "<<endl;break;}case 3:{int k;cout<<"请输入删除数据"<<endl;int s,judge=1;cin>>s;for(k=0;k<n;k++){if(data[k]==s)break;}if(k==n){cout<<"该数据不存在"<<endl;}else {Deletedata(Root,s);cout<<"删除成功";}cout<<"剩余关键码为:";for(int q=0;q<n;q++){if(q==k) q++;cout<<data[q]<<" ";}break;}case 4: Deleteall(Root,data,n);break;case 5: return;}}system("pause");}。