北邮数据结构实验—二叉排序树
数据结构_二叉排序树实验报告

日 期:
实验成绩:
批阅日期:
【本文档内容可以自由复制内容或自由编辑修改内容期待你的好评和关注,我们将会做得更好】
五、概要设计
为了实现上述操作,应以构造体为存储构造。实现如下:
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、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间: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");}。