计算机科学与技术课程设计.docx

上传人:b****3 文档编号:11720703 上传时间:2023-06-02 格式:DOCX 页数:24 大小:233.02KB
下载 相关 举报
计算机科学与技术课程设计.docx_第1页
第1页 / 共24页
计算机科学与技术课程设计.docx_第2页
第2页 / 共24页
计算机科学与技术课程设计.docx_第3页
第3页 / 共24页
计算机科学与技术课程设计.docx_第4页
第4页 / 共24页
计算机科学与技术课程设计.docx_第5页
第5页 / 共24页
计算机科学与技术课程设计.docx_第6页
第6页 / 共24页
计算机科学与技术课程设计.docx_第7页
第7页 / 共24页
计算机科学与技术课程设计.docx_第8页
第8页 / 共24页
计算机科学与技术课程设计.docx_第9页
第9页 / 共24页
计算机科学与技术课程设计.docx_第10页
第10页 / 共24页
计算机科学与技术课程设计.docx_第11页
第11页 / 共24页
计算机科学与技术课程设计.docx_第12页
第12页 / 共24页
计算机科学与技术课程设计.docx_第13页
第13页 / 共24页
计算机科学与技术课程设计.docx_第14页
第14页 / 共24页
计算机科学与技术课程设计.docx_第15页
第15页 / 共24页
计算机科学与技术课程设计.docx_第16页
第16页 / 共24页
计算机科学与技术课程设计.docx_第17页
第17页 / 共24页
计算机科学与技术课程设计.docx_第18页
第18页 / 共24页
计算机科学与技术课程设计.docx_第19页
第19页 / 共24页
计算机科学与技术课程设计.docx_第20页
第20页 / 共24页
亲,该文档总共24页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

计算机科学与技术课程设计.docx

《计算机科学与技术课程设计.docx》由会员分享,可在线阅读,更多相关《计算机科学与技术课程设计.docx(24页珍藏版)》请在冰点文库上搜索。

计算机科学与技术课程设计.docx

计算机科学与技术课程设计

一、课程设计题目

二叉平衡排序树

摘要问题描述:

从一棵空树开始创建,在创建过程中,保证树的有序性,同时还要针对树的平衡性做些调整。

最终要把创建好的二叉排序树转换为二叉平衡排序树。

  基本要求:

1.创建(插入、调整、改组)

开发工具:

windowsXP操作系统,Microsoftvisualc++6.0编译系统;

关键词:

C++;

 

二、设计主要目的及意义

目的:

2.熟悉二叉树的创建(插入、调整、改组),输出以及把二叉排序树转换为二

叉平衡排序树

3.更进一步掌握有关二叉排序树的操作

 

意义:

软件课程设计是计算机科学与技术专业软件方向的一个重要环节,是语言类课程学习的总结。

通过课程设计使我们加深对程序设计的理解,掌握程序开发的基本方法,深化学生面向对象的编程设计思想和新一代程序设计的逻辑思维方式,把课堂上所学到的多个单元串到一起,提高我们在软件设计过程中分析问题和解决问题的实际动手能力,使我们的理论知识和实践技能得到共同发展,最终提高我们解决问题和分析问题的能力。

为我们踏上工作岗位之前提供了一次专业研究和项目开发的宝贵实践机会,为今后的工作积累经验。

 

三、课程设计的过程

主要算法说明:

1.主要数据结构定义

typedefstructnodenode;

Structnode

{

Node*parent;

Node*left;

Node*right;

Intbalance;//左右子树高度之差

Intkey;

}

 

2.主要函数说明

IntscarchNode(intkey,node*root,node*parent):

按key查找结点

Node*minNode(node*root):

树root的最小结点

Node*maxNode(node*root):

树root的最大结点

Node*preNode(node*target):

求前驱结点

Node*nextNode(node*targer):

求后继结点

node*adjustAVL(node*root,node*parent,node*child);调整,保证二叉树的平衡性

Node*insertNode(intkey,node*root):

插入

Node*deletevode(intkey,node*root):

删除

Node*createAVL(int*data,intsize):

创建新的二叉树

Voidinterordertraverse(node*root):

中序遍历

Voidpreordertraverse(node*root):

先序遍历

 

3.二叉排序树的插入和删除

a.二叉排序树的插入

在二叉排序树插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义

插入过程:

若二叉排序树正存在,则返回根结点;

当结点不存在时,将待插入到根结点的关键字key和树根关键字parent->key进行比较.

若keykey,则插入到根的左子树中,否则,插入到根的右子树中.而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点作为一个新的树叶插入到二叉排序树中或者直到发现树已有相同关键字的结点为止,并且注意二叉树的平衡,时刻调整.

 

假设在二叉排序树上被删结点为*tp,其双亲结点为*parent,且不失一般性,可设*parent是*parent->left的左孩子.

下面分了3种情况进行讨论:

(1).若*parent结点为叶子结点,即PL和PR均为空树.由于删去叶子结点不破坏整棵树的结构,则只需要修改其双亲,结构点的指针即可.

(2).若*parent结点凡有左子树PL或者只有右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树即可.显然,作此修改也不破坏二叉排序树的特性.

(3).若*parent结点的左子树均不空,并且注意二叉树的平衡性,时刻调整.

 

4.中序遍历和先序遍历

Voidinterordertraverse(node*root)//中序遍历

{

If(root1=NULL)

{

Interordertraverse(root->left);

Printf("%d,%d\n,"root->key,root->balance);

Interordertraverse(root->right);

}

}

Voidpreordertraverse(node*root)//先序遍历

{

If(root!

=NULL)

{

Printf("%d,%d\n",root->key,root->balance);

Preorderstraverse(root->left);

Preorderstraverse(root->right);

}

}

5.动态平衡技术的概念

Adelson-Velskii和Landis提出了一个动态地保持二叉排序树平衡的方法,其基本思想是:

在构造二叉排序树的过程中,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性,如果是因插入结点而破坏了树的平衡性,则找出其中最小不平衡子树,在保持排序树特性的前提下,调整最小不平衡子树中各结点之间的连接关系,以达到新的平衡。

通常将这样得到的平衡二叉排序树简称为AVL树。

为了保证二叉排序树的高度为lgn,从而保证二叉排序树上实现的插入、删除和查找等基本操作的平均时间为O(lgn),在往树中插入或删除结点时,要调整树的形态来保持树的平衡。

使之既保持BST性质不变又保证树的高度在任何情况下均为O(lgn),从而确保树上的基本操作在最坏情况下的时间均为O(lgn)。

6.最小不平衡子树的概念

以离插入结点最近、且平衡因子绝对值大于1的结点作根结点的子树。

为了简化讨论,不妨假设二叉排序树的最小不平衡子树的根结点为A,则调整该子树的规律可归纳为下列四种情况:

图3平衡调整的4种基本类型(结点旁的数字是平衡因子)

(1)LL型:

新结点X插在A的左孩子的左子树里。

调整方法见图3(a)。

图中以B为轴心,将A结点从B的右上方转到B的右下侧,使A成为B的右孩子。

(2)RR型:

新结点X插在A的右孩子的右子树里。

调整方法见图3(b)。

图中以B为轴心,将A结点从B的左上方转到B的左下侧,使A成为B的左孩子。

(3)LR型:

  新结点X插在A的左孩子的右子树里。

调整方法见图3(c)。

分为两步进行:

第一步以X为轴心,将B从X的左上方转到X的左下侧,使B成为X的左孩子,X成为A的左孩子。

第二步跟LL型一样处理(应以X为轴心)。

(4)RL型:

  新结点X插在A的右孩子的左子树里。

调整方法见图3(d)。

分为两步进行:

第一步以X为轴心,将B从X的右上方转到X的右下侧,使B成为X的右孩子,X成为A的右孩子。

第二步跟RR型一样处理(应以X为轴心)。

 

Node*adjustAVL(node*root,node*parent,node*child)

主要有四种调整类型根据平衡因子主要有LR,LL,RL,RR.

(1)根据parent->balance的值为2时,child->balance==-1时是LR型,否则为LL型.

(2)Parent->balance的值为-2时,child->balance==1时是RL型,否则为RR型.

8.程序代码设计:

(代码部分详见附录)

 

9.运行界面

运行界面如下图所示:

【注:

运行时所执行的操作标注在截图的上方】

选择1,输入序列(13,24,37,90,53)创建一刻二叉平衡树,以0为结尾;

序列输入完成以后按回车,再选择4,中序输出该树;

继续其它操作,选择2,插入一个新结点,其值为1,插入后选择4中序输出该树;

继续其它操作,选择3删除一个结点,这里删除结点1,删除后先序输出该树;

继续其它操作,输入6,6不是1-5中的树,程序自动退出;

注:

程序存在已知缺陷(结点删除后的平衡问体,某种状态下删除特殊位置的结点会出现异常),有待弥补。

 

四、重点及难点

重点:

1)任一结点的左右子树的高度均相同(如满二叉树),则二叉树是完全平衡的。

通常,只要二叉树的高度为O(1gn),就可看作是平衡的。

2)平衡的二叉排序树指满足BST性质的平衡二叉树。

3)AVL树中任一结点的左、右子树的高度之差的绝对值不超过1。

在最坏情况下,n个结点的AVL树的高度约为1.44lgn。

而完全平衡的二叉树度高约为lgn,AVL树是接近最优的。

难点:

平衡二叉树的生成是数据结构中一个重要的存储结构。

由于本程序的输入较多,所以输入数据时必须小心细致。

本程序比较复杂,需要使用结构体并使用了指针。

必须将程序分解为多个子程序以降低编写难度。

想起了软工老师的一句话:

"难事破与易",再复杂的事,拆成一个个简单的小部分,逐个击破,在拼凑起来,复杂的事也变的简单了。

适当使用全局常量可以控制有效控制内存溢出。

由于程序较大,调试时多人协作能更容易易找出程序并成功修改。

 

五、主要结论

通过平衡二叉树的生成程序的设计,我们很好的理解了平衡二叉树的生成和各项操作的相关知识,同时还较好的掌握了动态查找相关概念。

六、致谢

本课程设计的完成,首先感谢母校——河北工程大学的辛勤培育之恩。

本系统是在刘云老师直接指导下完成的,刘老师从论文的选题,设计计划的安排到具体功能的实现,以及说明书的撰写直至定稿的全过程都给予了精心的指导和严格的要求,对本论文的最后完成给予了莫大的帮助。

在设计过程中刘云老师在百忙中挤出时间多次给予指导,提出了许多宝贵的修改意见。

在这里首先要感谢刘云老师。

其次要感谢程天明和付向飞同学,他们利用自己的宝贵时间与我一起研究系统的设计方面的问题,并且结合自己的经验,给我提出的宝贵的意见和建议,使我的系统得以进一步的完善。

在此也向他们表示由衷的感谢。

然后还要感谢大学以来所有的老师,为我们打下计算机专业知识的基础;同时还要感谢所有的同学们,正是因为有了你们的支持和鼓励。

此次课程设计才会顺利完成。

 

七、参考文献

[1]王春红,梁普选,王建亮.Delphi程序开发.北京:

机械工业出版社2003

[2]张基温,杨晓玲.VisualBasic程序开发教程.北京:

清华大学出版社,2004

[3]陈俊源.Delphi程序设计实用教程.北京:

电子工业出版社,2000

[4]段兴.Delphi7程序设计教程[M].北京:

清华大学出版社,2003

[5]张宏林,陆华,王思学.Delphi6编程指南[M].北京:

人民邮电出版社,2000

 

 

八、附录:

程序清单

#include

#include//cout

#include//setw

#defineLH1//左高

#defineEH0//等高

#defineRH-1//右高

#defineTRUE1

#defineFALSE0

inttaller=0;//taller反映T长高与否

//二叉排序树的类型定义

typedefstructBSTNode

{

intdata;//结点值

intbf;//结点的平衡因子

structBSTNode*lchild,*rchild;//分别指向左右孩子的指针

}BSTNode,*BSTree;//同时声明一个BSTNode和一个指针类型的*BSTree

//树的中序遍历的递归算法,一并输出它的平衡因子和左右结点值

voidMidOrder(BSTreeT)

{

//中序遍历的特点是:

当二叉树为空,则空操作;否则

//1.中序遍历左子树;

//2.访问根结点;

//3.中序遍历右子树。

if(T->lchild)MidOrder(T->lchild);

if(T->data)

{//以适当的形式格式化输出各个结点及其附加信息可以方便用户重构二叉树

cout<data<bf;

if(T->lchild)cout<lchild->data;elsecout<

if(T->rchild)cout<rchild->data;elsecout<

cout<

}

if(T->rchild)MidOrder(T->rchild);

}

//对以p为根的树作右旋处理,处理之p指向新的树根结点即旋转处理之前的左子树根结点

BSTreeR_Rotate(BSTreep)

{

BSTNode*lc;//声明BSTNode*临时变量

lc=p->lchild;//lc指向的*p的左子树根结点

p->lchild=lc->rchild;//lc的右子树挂接为*p的左子树

lc->rchild=p;

p=lc;//p指向新的根结点

returnp;//返回新的根结点

}

//对以p为根的树作左旋处理,处理之p指向新的树根结点即旋转处理之前的右子树根结点

BSTreeL_Rotate(BSTreep)

{

BSTNode*rc;//声明BSTNode*临时变量

rc=p->rchild;//rc指向的*p的右子树根结点

p->rchild=rc->lchild;//rc的左子树挂接为*p的右子树

rc->lchild=p;

p=rc;//p指向新的根结点

returnp;//返回新的根结点

}

//对以指针T所指结点为根的二叉树作左平衡旋转处理,本算法结束时指针T指向新的根结点

BSTreeLeftBalance(BSTreeT)

{

BSTNode*lc,*rd;

lc=T->lchild;//lc指向*T的左子树根结点

switch(lc->bf)//检查*T的左子树平衡度,并做相应的平衡处理

{

caseLH:

//新结点插入在*T的左孩子的左子树上,要做单右旋处理

T->bf=lc->bf=EH;

T=R_Rotate(T);

break;

caseRH:

//新结点插入在*T的左孩子的右子树上,要做双旋处理

rd=lc->rchild;//rd指向*T的左孩子的右子树根

switch(rd->bf)//修改*T及其左孩子的平衡因子

{

caseLH:

T->bf=RH;

lc->bf=EH;

break;

caseEH:

T->bf=lc->bf=EH;

break;

caseRH:

T->bf=EH;

lc->bf=LH;

break;

}

rd->bf=EH;

T->lchild=L_Rotate(T->lchild);//对*T的左孩子做左旋平衡处理

T=R_Rotate(T);//对*T做右旋处理

}

returnT;

}

//对以指针T所指结点为根的二叉树作右平衡旋转处理,本算法结束时指针T指向新的根结点

BSTreeRightBalance(BSTreeT)

{

BSTreerc,ld;

rc=T->rchild;//rc指向*T的右子树根结点

switch(rc->bf)//检查*T的右子树平衡度,并做相应的平衡处理

{

caseRH:

//新结点插入在*T的右孩子的右子树上,要做单右旋处理

T->bf=rc->bf=EH;

T=L_Rotate(T);

break;

caseLH:

//新结点插入在*T的右孩子的左子树上,要做双旋处理

ld=rc->lchild;//ld指向*T的右孩子的左子树根

switch(ld->bf)//修改*T及其右孩子的平衡因子

{

caseLH:

T->bf=LH;

rc->bf=EH;

break;

caseEH:

T->bf=rc->bf=EH;

break;

caseRH:

T->bf=EH;

rc->bf=RH;

break;

}

ld->bf=EH;

T->rchild=R_Rotate(T->rchild);//对*T的右孩子做右旋平衡处理

T=L_Rotate(T);//对*T做左旋处理

}

returnT;

}

//若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据元素为e的新结点,并返回插入后所建成的平衡二叉排序树,否则返回NULL.若因插入而使二叉数失去平衡,则作平衡旋转处理,布尔变量taller反映T长高与否

BSTreeInsertAVL(BSTreeT,inte)

{

BSTreep;

//插入新结点,树长高置taller为TRUE

if(!

T)

{

T=(BSTree)malloc(sizeof(BSTNode));

T->data=e;

T->lchild=T->rchild=NULL;

T->bf=EH;

taller=TRUE;

}

else

{

//树中存在和e有相同关键字的结点则不再插入

if(e==T->data)

{

taller=FALSE;

returnNULL;

}

//值小于则继续在树的左子树中搜索

if(edata)

{

p=InsertAVL(T->lchild,e);//插入到左子树且左子树长高

if(p)

{

T->lchild=p;

if(taller)

{

switch(T->bf)//检查*T的平衡度

{

caseLH:

//原本左子树比右子树高,需要做左平衡处理

T=LeftBalance(T);

taller=FALSE;

break;

caseEH:

//原本左、右子树同高,现因左子树争高而使树增高

T->bf=LH;

taller=TRUE;

break;

caseRH:

//原本右子树比左子树高,现在左右子树等高

T->bf=EH;

taller=FALSE;

break;

}

}

}

}

//继续在*T的右子树中搜索

else

{

//插入到右子树且使右子树长高

p=InsertAVL(T->rchild,e);

if(p)

{

T->rchild=p;

if(taller)

{

switch(T->bf)//检查*T的平衡度

{

caseLH:

//原本左子树比右子树高,现在左右子树等高

T->bf=EH;

taller=FALSE;

break;

caseEH:

//原本左、右子树同高,现因右子树增高而使树增高

T->bf=RH;

taller=TRUE;

break;

caseRH:

//原本右子树比左子树高,需要做右平衡处理

T=RightBalance(T);

taller=FALSE;

break;

}

}

}

}

}

returnT;

}

//建立新结点

BSTreeCreatNode(intnodeValue)

{

BSTreenode;

node=(BSTree)malloc(sizeof(BSTree));

node->data=nodeValue;

node->bf=0;

node->lchild=NULL;

node->rchild=NULL;

returnnode;

}

//在屏幕打印菜单函数

intPrintMenu()

{

intuserChose;

cout<<"---------------------"<

cout<<"1.创建一棵二叉排序树"<

cout<<"2.向排序树插入新结点转化成平衡树"<

cout<<"3.中序遍历输出平衡树"<

cout<<"n.选择其它将退出程序"<

cout<<"---------------------"<

cout<<"请选择你的操作:

";

cin>>userChose;

returnuserChose;

}

//新建二叉树函数

BSTreeBuildTree(BSTreer)

{

//如果传入根结点不为空,则树已构建过,退出函数

if(r!

=NULL)

{

cout<<"二叉平衡树已经创建!

";

returnNULL;

}

//根结点为空则开始构建

cout<<"请输入结点值,输入零则结束"<

intnodeValue;

cin>>nodeValue;

while(nodeValue)//插入任

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技 > 纺织轻工业

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2