沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:二叉排序树算法院(系):计算机学院专业:计算机科学与技术班级:04010103学号:2010040101097姓名:郭胜龙指导教师:丁一军此页为任务书目录1 课程设计介绍 (1)1.1课程设计内容 (1)1.2课程设计要求 (1)2 课程设计原理 (2)2.1课设题目粗略分析 (2)2.2原理图介绍 (2)2.2.1 功能模块图 (2)2.2.2 main(主函数) (2)2.2.3 SearchBST(查找) (3)2.2.4 InsertBST(插入) (4)2.2.5 CreatBST(建立) (4)2.2.6 DeleteBST(删除) (4)2.2.7 PreOrder(先序遍历) (5)2.2.8 InOrder(中序遍历) (5)3 数据结构分析 (7)3.1存储结构 (7)3.2算法描述 (7)4 调试与分析 (12)4.1调试过程 (12)4.2程序执行过程 (12)参考文献 (15)附录(关键部分程序清单) (16)沈阳航空航天大学课程设计报告1 课程设计介绍1.1 课程设计内容题目内容:1.构造二叉排序树;2.输出该二叉排序树的先序、中序遍历序列;3.删除该二叉排序树的任意一个结点;4.输出删除后的二叉排序树的先序、中序遍历序列。
1.2课程设计要求题目要求:1.按要求建立不同的二叉排序树;2.数据自定3.独立完成课程设计任务2 课程设计原理2.1课设题目粗略分析根据课设题目要求,拟将整体程序分为七大模块。
以下是七个模块的大体分析:main ():主函数模块SearchBST ():查找相应的结点 InsertBST1():插入一个新的结点 CreatBST ():创建一棵二叉排序树 DeleteNode ():删除结点PreOrder ()对二叉排序树进行先序遍历 InOrder ()对二叉排序树进行中序遍历2.2 原理图介绍2.2.1 功能模块图图2.2.1 功能模块结构图2.2.2 main (主函数)功能:连接各个函数,确定他们的执行顺序和条件。
二叉排序树算法主模块查找模块 插入模块 建立模块 删除模块 先序遍历模块 中序遍历模块图2.2.2主函数流程图2.2.3 SearchBST (查找)功能:查找相应的结点。
图2.2.3 查找操作的流程图开始选择功能Choose=1 建立二叉排序树Choose=2 删除x 结点Choose=3 先序遍历二叉排Choose=0 退出Choose=4 中序遍历二叉排A结束AYY开始T->data==key s=TT->data>keys=SearchBST(T->rchild)s=SearchBST(T->lchild)NN返回s结束2.2.4 InsertBST (插入)功能:插入一个新的结点。
图2.2.4 插入操作的流程图2.2.5 CreatBST (建立)功能:建立一个已知数据的二叉排序树。
图2.2.5 建立操作的流程图2.2.6 DeleteBST (删除)功能:删除值为x 的结点。
YY开始T==NULL T=ss->data>T->datas=InserBST(T->rchild)s=InsertBST(T->lchild)NN结束开始输入结点数n调用插入函数结束开始调用查找函数删除p结点右子树连在左子树上左子树连在p结点的父母节点上结束图2.2.6 删除操作的流程图2.2.7 PreOrder(先序遍历)功能:对二叉排序树进行先序遍历,并输出序列。
开始访问TPreOrder(T->rchild)PreOrder(T->lchild)结束图2.2.7 先序遍历的流程图2.2.8 InOrder(中序遍历)功能:对二叉排序树进行先序遍历,并输出序列。
开始InOrder(T->rchild)访问TInOrder(T->lchild)结束图2.2.8 中序遍历的流程图沈阳航空航天大学课程设计报告错误!未指定书签。
3 数据结构分析3.1 存储结构定义一个链表式的二叉排序树,用链表的方式构造结点,存储二叉排序树中的结点、结点类型和指针类型如下:typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;3.2 算法描述1、二叉排序树的查找算法(1)若二叉排序树为空,则查找失败。
(2)否则,将根结点的关键字与待查关键字进行比较,若相等,则查找成功;若根节点关键字大于待查值,则进入左子树重复次步骤,否则,进入右子树进行此步骤;若在查找过程中遇到二叉排序树的叶子节点时,还没有找到待查节点,则查找不成功。
算法如下:BiTree SearchBST1(BiTree T, int key){//在根指针T所指二叉排序树中递归查找关键字等于 key 的数据元素//若成功,返回指向该数据元素结点的指针,否则返回空指针;s为返回 //指针BiTree s;if(T==NULL) return NULL;else if(T->data==key) s=T;else if(T->data>key) //key大于当前结点的关键字,则查找左子树s=SearchBST1(T->lchild,key);else//key小于当前结点的关键字则查找右子树s=SearchBST1(T->rchild,key);return s;}3、二叉排序树的节点插入算法在二叉排序树中插入一个新节点,首先要查找该节点在二叉排序树中是否已经存在。
若二叉排序树中不存在关键字等于x的节点,则插入。
将一个关键字值为x的节点s插入到二叉排序树中,可以用下面的方法:(1)若二叉排序树为空,则关键字为x的节点s成为二叉排序树的根(2)若二叉排序树非空,则将x与二叉排序树根进行比较,如果x的值等于根节点关键值,则停止插入;如果x的根节点值小于根节点关键值,则将x插入左子树;如果x的值大于根节点关键字的值,则将x插入右子树。
在左右两个子树的插入方法与整个二叉排序树相同。
算法如下:void InsertBST1(BiTree &T,BiTNode *s){//在二叉树排序树T中,插入一个结点s的递归算法BiTree t;t=SearchBST1(T,s->data);//若s的关键字不在T中出现,则插入if(!t){if(T==NULL)T=s; //空树时作为根结点else if(s->data<T->data)InsertBST1(T->lchild,s); //将s插入T的左子树 elseInsertBST1(T->rchild,s); //将s插入T的右子树}}3、二叉排序树的节点删除算法在二叉排序树中删除节点,首先要进行查找操作,以确定被删除的节点是否在二叉排序树中若不在,则不做任何操作;否则,假设要删除的节点为*p,节点*p的父节点为*f,并假设*p是*f的左孩子。
根据被删除节点*p有无孩子,删除部分可做以下3中情况讨论:(1)若*p为叶子节点,则可令其父节点*f的左孩子指针域为空,直接将其删除。
(2)若*p节点只有右子树或左子树,则可以将p的左子树或右子树直接改为其双亲节点f的左子树。
(3)若*p既有左子树又有右子树;将节点*s为*p的中序前驱。
首先找到*p 的中序前驱节点*s,然后用节点*s的值代替节点*p的值,再将节点*s删除,节点*s的原左子树改为*s的双亲节点*q的右子树;算法如下:DeleteNode(BiTree &T, int x){//从二叉树排序树T中删除任意结点,其关键字为xBiTree p,q,pParent,pChileNode;p=T; //从根结点开始查找pParent = NULL;// T的双亲为NULLwhile (p)// 开始查找关键字为x的结点p,及双亲pParent{if (x == p->data)break;pParent = p;p = x > p->data ? p->rchild : p->lchild;}if (p==NULL){printf("要删除的结点不存在\n");return false;} // 至此已找到目标结点p// pChileNode = p存在的孩子或NULL,左右都存在时,取左pChileNode = p->lchild!= NULL ? p->lchild : p->rchild;if(p->lchild==NULL||p->lchild==NULL){if (pParent == NULL)T= pChileNode;else{if(p==pParent->lchild)pParent->lchild= pChileNode;elsepParent->rchild = pChileNode;}free(p);//释放空间} // 当2个孩子都存在时else{//pChileNode已指向p->lchildq=p;while (pChileNode->rchild){//在p的左字树中查找中序p的前驱pChileNode,q为其双亲 q=pChileNode;pChileNode = pChileNode->rchild;}p->data=pChileNode->data;//p的前驱pChileNodede 的关键值赋给pif(q!=p) //将删除p转化为删除pChileNodede(最多只有左字树)结点{q->rchild=pChileNode->lchild;//p的左字树有右孩子 }else{q->lchild=pChileNode->lchild;//p的左字树有右孩子 }free(pChileNode);}return true;}4 调试与分析4.1 调试过程在调试程序是主要遇到以下几类问题:1.二叉树的存储结构的选择2.界面函数的调整3.删除的时候二叉树的调整4.2 程序执行过程执行过程如下图:图4.2.1 界面图图4.2.2 建立二叉排序树图4.2.3 先序遍历序列图4.2.4 中序遍历序列图4.2.5 删除结点图4.2.6 删除后的先序遍历序列图4.2.7 删除后的中序遍历序列沈阳航空航天大学课程设计报告错误!未指定书签。
参考文献[1] 殷人昆,等. 数据结构(用面向对象方法与C++描述)[M]. 北京:清华大学出版社,2002.[2] 宁正元,等. 算法与数据结构习题精解和实验指导[M]. 北京:清华大学出版社,2002.[3] 严蔚敏,吴伟民.数据结构[M].北京:清华大学出版社,2007.[4] 张长海,陈娟.C程序设计[M].北京:高等教育出版社,2004.[5] 谭浩强.C程序设计[M].北京:清华大学出版社,2005.附录(关键部分程序清单)#include <stdio.h>#include <malloc.h>#include <stdlib.h>typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;/************************查找**************************/BiTree SearchBST1(BiTree T, int key){//在根指针T所指二叉排序树中递归查找关键字等于 key 的数据元素//若成功,返回指向该数据元素结点的指针,否则返回空指针;s为返回 //指针BiTree s;if(T==NULL) return NULL;else if(T->data==key) s=T;else if(T->data>key) //key大于当前结点的关键字,则查找左子树s=SearchBST1(T->lchild,key);else//key小于当前结点的关键字则查找右子树s=SearchBST1(T->rchild,key);return s;}/************************插入**************************/void InsertBST1(BiTree &T,BiTNode *s){//在二叉树排序树T中,插入一个结点s的递归算法BiTree t;t=SearchBST1(T,s->data);//若s的关键字不在T中出现,则插入if(!t){if(T==NULL)T=s; //空树时作为根结点else if(s->data<T->data)InsertBST1(T->lchild,s); //将s插入T的左子树elseInsertBST1(T->rchild,s); //将s插入T的右子树}}/***********************建立****************************/BiTree CreatBST(int n){//建立n个关键字的二叉排序树,//从键盘输入调建立n个关键字依次用InsertBST1(插入函数),//返回根结点TBiTree T,s;int i,key;T=NULL;printf("建树过程:\n");for(i=1;i<=n;i++){printf("插入结点关键值:\n");scanf("%d",&key);s=(BiTree)malloc(sizeof(BiTNode));//开辟存储单元,并对结点赋值s->data=key;s->lchild=NULL; s->rchild=NULL;InsertBST1(T,s); //调用插入算法}return T;}/***********************删除*****************************/ DeleteNode(BiTree &T, int x){//从二叉树排序树T中删除任意结点,其关键字为xBiTree p,q,pParent,pChileNode;p=T; //从根结点开始查找pParent = NULL;// T的双亲为NULLwhile (p)// 开始查找关键字为x的结点p,及双亲pParent{if (x == p->data)break;pParent = p;p = x > p->data ? p->rchild : p->lchild;}if (p==NULL){printf("要删除的结点不存在\n");return false;} // 至此已找到目标结点p// pChileNode = p存在的孩子或NULL,左右都存在时,取左pChileNode = p->lchild!= NULL ? p->lchild : p->rchild;if(p->lchild==NULL||p->lchild==NULL){if (pParent == NULL)T= pChileNode;else{if(p==pParent->lchild)pParent->lchild= pChileNode;elsepParent->rchild = pChileNode;}free(p);//释放空间} // 当2个孩子都存在时else{//pChileNode已指向p->lchildq=p;while (pChileNode->rchild){//在p的左字树中查找中序p的前驱pChileNode,q为其双亲 q=pChileNode;pChileNode = pChileNode->rchild;}p->data=pChileNode->data;//p的前驱pChileNodede 的关键值赋给p if(q!=p) //将删除p转化为删除pChileNodede(最多只有左字树)结点 {q->rchild=pChileNode->lchild;//p的左字树有右孩子 }else{q->lchild=pChileNode->lchild;//p的左字树有右孩子 }free(pChileNode);}return true;}/**********************先序遍历************************/void PreOrder(BiTree T){if(T!=NULL){printf("%3d",T->data);PreOrder(T->lchild);PreOrder(T->rchild);}}/*********************中序遍历**************************/void InOrder(BiTree T){if(T!=NULL){InOrder(T->lchild);printf("%3d",T->data);InOrder(T->rchild);}}/*********************主函数******************************/void main(){int n,x,choose;BiTree T;while(1){printf("\n\n*******************************************\n"); printf("************************************\n");printf("二叉排序树算法\n");printf("************************************\n"); printf("请选择操作:\n");printf("0.退出\n");printf("1.建立一棵二叉排序树\n");printf("2.删除一个任意结点\n");printf("3.先序遍历序列\n");printf("4.中序遍历序列\n");printf("Please choose:");scanf("%d",&choose);switch(choose){case 1:system("cls");printf("输入结点个数n=:\n");scanf("%d",&n);T=CreatBST(n);system("cls");break;case 2:system("cls");printf("输入想要删除的结点x=:\n"); scanf("%d",&x);DeleteNode(T, x);system("cls");break;case 3:system("cls");printf("先序遍历序列:\n");PreOrder(T);printf("\n");break;case 4:system("cls");printf("中序遍历序列:\n");InOrder(T);printf("\n");break;default:exit(0);}}}沈阳航空航天大学课程设计报告课程设计总结:指导教师评语:指导教师(签字):年月日课程设计成绩。