数据结构B线段树及其应用.docx

上传人:b****6 文档编号:7711272 上传时间:2023-01-25 格式:DOCX 页数:54 大小:348.52KB
下载 相关 举报
数据结构B线段树及其应用.docx_第1页
第1页 / 共54页
数据结构B线段树及其应用.docx_第2页
第2页 / 共54页
数据结构B线段树及其应用.docx_第3页
第3页 / 共54页
数据结构B线段树及其应用.docx_第4页
第4页 / 共54页
数据结构B线段树及其应用.docx_第5页
第5页 / 共54页
点击查看更多>>
下载资源
资源描述

数据结构B线段树及其应用.docx

《数据结构B线段树及其应用.docx》由会员分享,可在线阅读,更多相关《数据结构B线段树及其应用.docx(54页珍藏版)》请在冰豆网上搜索。

数据结构B线段树及其应用.docx

数据结构B线段树及其应用

东北大学信息科学与工程学院

数据结构课程设计报告

题目线段树及其应用

课题组长余灏然

课题组成员魏嘉张越

专业名称计算机科学与技术

班级计算机1307

指导教师杨雷

 

2015年1月

 

课程设计任务书

题目:

线段树及其应用

问题描述:

在实际应用中,常遇到与区间有关的操作,比如统计若干矩形并集的面积,记录一个区间的最大最小值及总量,并在区间的插入、删除和修改中维护这些数据。

线段树的定义是利用树形二分结构所建立的一种数据结构,能够高效的完成这些操作。

设计要求:

设计线段树的抽象数据类型及其实现。

(1)实现线段树的ADT。

(2)实现线段树的简单应用。

            

指导教师签字:

2014年12月28日

目录

1课题概述1

1.1课题任务1

1.2课题原理1

1.3相关知识2

2需求分析2

2.1课题调研2

2.2用户需求分析2

3方案设计2

3.1总体功能设计2

3.2数据结构设计2

3.3函数原型设计2

3.4主算法设计3

3.5用户界面设计3

4方案实现4

4.1开发环境与工具4

4.2程序设计关键技术4

4.3个人设计实现(按组员分工)

4.3.1余灏然设计实现4

4.3.2魏嘉设计实现9

4.3.3张越设计实现15

5测试与调试17

5.1个人测试(按组员分工)17

5.1.1余灏然测试17

5.1.2魏嘉测试25

5.1.3张越测试27

5.2组装与系统测试30

5.3系统运行31

6课题总结32

6.1课题评价32

6.2团队协作32

6.3个人设计小结(按组员分工)32

6.3.1余灏然设计小结32

6.3.2魏嘉设计小结32

6.3.3张越设计小结33

7附录A课题任务分工34

A-1课题程序设计分工34

A-2课题报告分工35

附录B课题设计文档(光盘)

B-1课程设计报告(电子版)

B-2源程序代码(*.H,*.CPP)

B-3工程与可执行文件)

B-4屏幕演示录像文件(可选)

附录C用户操作手册(可选)36

C.1运行环境说明36

C.2操作说明36

 

 

1课题概述

1.1课题任务

在实际应用中,常遇到与区间有关的操作,比如统计若干矩形并集的面积,记录一个区间的最大最小值及总量,并在区间的插入、删除和修改中维护这些数据。

线段树的定义是利用树形二分结构所建立的一种数据结构,能够高效的完成这些操作。

我们选择利用线段树这种结构来建立一个车票购票系统。

【设计要求】

设计线段树的抽象数据类型及其实现。

(1)实现线段树的ADT。

(2)实现线段树的简单应用。

1.2课题原理

线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)!

流程图如下:

 

1.3相关知识

前序遍历树,将树变成链表,用于存储;

Si与Sj用于测试,可删除;

2需求分析

2.1课题调研

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。

因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。

2.2用户需求分析

利用线段树高效快速的运行车票出售系统。

功能需求

(1)输入功能和显示功能

(2)购买车票、查询车票余额

(3)添加、修改、删除站点信息

(4)读取文件功能和保存文件功能

(5)需要用户友好的界面以便用户方便使用

3方案设计

3.1总体功能设计

线段树

3.2数据结构设计

前序遍历树,将树变成链表,用于存储。

3.3函数原型设计

函数原型

功能描述

voidTreeToList(TreeT,list&p)

前序遍历树,将树变成链表,用于存储。

voidListToTree(Tree&T,list:

:

iterator&iterP)

链表还原成树

intLoading(Tree&T)

读取数据将数据还原成树

voidprint(list&p)

显示乘车顺序

TreeFind(inta,TreeT)

寻找叶子

voidBuyTicket(inta,intb,intn,Tree&T)

购票

voidCheck()

检查数据文件

voidwelcome()

初始界面显示

voidInquire(TreeT,list&p)

查询车票数量

voidintitle(list&p)

站号对应站名的处理

3.4主算法设计

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。

因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。

3.5用户界面设计

Dos界面

 

输入后:

4方案实现

4.1开发环境与工具

主要编程环境:

MicrosoftVisualStudioC++6.0

编程工具:

C++。

4.2程序设计关键技术

线段树及其应用:

(1)C#语言的学习和MicrosoftVisualStudio2008的使用方法,因为未学习过此语言,学会使用C#和开发工具是程序设计的关键。

(2)线段树的实现问题,线段树的实现还是相对复杂的,我们从网上,书籍查阅了许多资料,进行了多次debug才完成此部分。

(3)多人程序的融合性问题,由于没怎么接触过多人写程序,每个人写的程序必须能够很好组合。

4.3个人设计实现(按组员分工)

4.3.1余灏然设计实现

Main函数

#include"head.h"

#include"save.cpp"

#include"StationName.cpp"

#include"buy.cpp"

#include"check.cpp"

#include"inquire.cpp"

#include"frame.cpp"

voidmain()

{

listp;

TreeT;

inti,j,a,b,n,t=0;//t值用于判断第一次"重新生成线段树"时是否执行DelData(T),t=0不执行t=1执行

Check();//检查数据文件是否丢失

t=Loading(T);//读取线段树数据

Loading2(p);//读取站名链表数据

welcome();

while

(1)

{

system("cls");frame();

gotoxy(25,8);cout<<"1.购票与查询";

gotoxy(25,9);cout<<"2.管理功能";

gotoxy(25,10);cout<<"3.退出";

gotoxy(25,12);cout<<"----请选择功能:

";

cin>>i;

system("cls");

if(i==1)

{

while

(1)

{

print(p);

cout<

";

cin>>j;

if(j==1)

{

cout<<"请分别输入出发站、到达站号及购买票数:

";

cin>>a>>b>>n;

if(a

if(a>b)BuyTicket2(a,b,n,T);

}

if(j==2)Inquire(T,p);

if(j==3)break;

}

}

if(i==2)

{

while

(1)

{

system("cls");

cout<<"请选择(1.重新生成线段树2.改变站名对应站号3.删除树并初始化4.返回):

";

cin>>j;

if(j==1)

{

cout<<"请输入线段区间(a,b)[必须符合0

";

cin>>a>>b;

if(t)DelData(T);

CreateTree(T,a,b);SaveTree(T);

t=1;

}

if(j==2)intitle(p);

if(j==3)DelData(T);

if(j==4)break;

}

}

if(i==3)exit(0);

}//while尾

}

save.cpp

#include"head.h"

voidTreeToList(TreeT,list&p)//前序遍历树,将树变成链表,用于存储,

{

SaveDataa;

if(T!

=NULL)

{

a.k=1;

a.Si=T->i;a.Sj=T->j;

a.Snum=T->num;a.Snum2=T->num2;

p.push_back(a);

TreeToList(T->lchild,p);

TreeToList(T->rchild,p);

}

else

{

a.k=0;

//a.Si=-1;a.Sj=-1;//Si与Sj用于测试,可删除

p.push_back(a);

}

}

voidSaveTree(TreeT)

{

FILE*fp;

SaveDatah;

listp;

list:

:

iteratoriterP=p.begin();

TreeToList(T,p);

iterP=p.begin();

fp=fopen("TicketData.dat","wb");

while

(1)

{

h.k=iterP->k;h.Si=iterP->Si;h.Sj=iterP->Sj;

h.Snum=iterP->Snum;h.Snum2=iterP->Snum2;

fwrite(&h,sizeof(SaveData),1,fp);

iterP++;

if(iterP==p.end())break;

}

SaveDatat;

t.k=-1;//t->k=-1表链表尾

fwrite(&t,sizeof(SaveData),1,fp);

fclose(fp);

//cout<<"存储成功!

"<

}

voidListToTree(Tree&T,list:

:

iterator&iterP)//链表还原成树

{

if(iterP->k==0){T=NULL;iterP++;}

else

{

if(!

(T=(Btree*)malloc(sizeof(Btree))))exit(-1);

T->i=iterP->Si;T->j=iterP->Sj;T->num=iterP->Snum;T->num2=iterP->Snum2;

iterP++;

ListToTree(T->lchild,iterP);

ListToTree(T->rchild,iterP);

}

}

intLoading(Tree&T)//读取数据将数据还原成树

{

listp;

list:

:

iteratoriterP;

FILE*fp;

SaveDatah;

fp=fopen("TicketData.dat","rb");

fread(&h,sizeof(SaveData),1,fp);

if(h.k==-1)

{cout<<"--------无数据内容。

"<

while(h.k!

=-1)//判断是不是链表尾

{

p.push_back(h);

fread(&h,sizeof(SaveData),1,fp);

}

fclose(fp);

iterP=p.begin();

ListToTree(T,iterP);

//cout<<"数据读取成功,已生成树。

"<

return1;

}

intDelData(TreeT)

{

DestroyTree(T);

FILE*fp;

fp=fopen("TicketData.dat","wb+");//不写入内容,即可清除数据

fclose(fp);

return1;

}

inquire.cpp

#include"head.h"

TreeFind(inta,TreeT);

voidInquire(TreeT,list&p)//查询车票数量

{

inti=0;

Treet;

list:

:

iteratoriterP=p.begin();

cout<

"<

while

(1)

{

t=Find(iterP->k,T);

cout<k<<"号站-"<name<<"===>";

iterP++;

cout<k<<"号站-"<name<<":

";

cout<<(max-t->num)<

iterP++;

if(iterP==p.end())break;

elseiterP--;

}

cout<

while

(1)

{

cout<k<<"号站-"<name<<"===>";

iterP--;

cout<k<<"号站-"<name<<":

";

t=Find(iterP->k,T);

cout<<(max-t->num2)<

iterP--;

if(iterP==p.end())break;

elseiterP++;

}

}

4.3.2魏嘉设计实现

head.h

#ifndef_HEAD_H

#define_HEAD_H//运用#ifndef避免重复定义

#include"iostream"

#include"stdio.h"

#include"windows.h"

#include"conio.h"

#include

usingnamespacestd;

#definemax100//每站票数的最大上限

typedefstructNode{

inti,j;//分别表示线段树左右节点

intnum;//存储数据,表示当前已出售票数

intnum2;//返程

structNode*lchild,*rchild;

}Btree,*Tree;

typedefstructstation{

intk;//站点所对应的数字

charname[20];

}staname;

typedefstructsave{

intk;//k=1时储存节点信息,k=0时代表空格不存储其他信息,k=-1时表示链表尾(NULL不知为何不好使=A=)

intSi,Sj;

intSnum;

intSnum2;

}SaveData;

intCreateTree(Tree&T,inta,intb)

{

if(b

{

cout<<"error!

"<

returnNULL;

}

T=(Btree*)malloc(sizeof(Btree));

T->i=a;T->j=b;T->num=-1;T->num2=-1;//只有树的叶子节点才用于存储数据,其他非叶子节点令其值为-1

if(b-a>1)

{

CreateTree(T->lchild,a,(a+b)/2);

CreateTree(T->rchild,(a+b)/2,b);

}

else

{

T->lchild=NULL;

T->rchild=NULL;

T->num=0;//初始化为0

T->num2=0;

}

return1;

}

 

voidDestroyTree(Tree&T)//删除时用这个,判断树是否已为空,若不空则执行Destroy(TreeT);

{

intDestroy(TreeT);

if(T->num==-1){Destroy(T);cout<<"线段树已销毁。

"<num=-1

elsecout<<"树已为空,无需销毁。

"<

}

intDestroy(TreeT)//完全销毁线段树

{

if(T==NULL)return1;

Destroy(T->lchild);

Destroy(T->rchild);

free(T);

return1;

}

voidPreOrder(TreeT)//前序遍历树

{

if(T!

=NULL)

{

cout<i<j<

PreOrder(T->lchild);

PreOrder(T->rchild);

}

else

cout<<"!

!

"<

}

voidgotoxy(intx,inty)//光标移动x为列坐标,y为行坐标

{

COORDpos={x,y};

HANDLEhOut=GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(hOut,pos);

}

#endif

StationName.cpp

#include"head.h"

#include"string.h"

voidintitle(list&p)//站号对应站名的处理

{

voidLoading2(list&p);

voidfirstuse();

list:

:

iteratoriterP;

inti,j;

charb[20];

stanameh;

FILE*fp;

while

(1)

{

system("cls");

iterP=p.begin();

fp=fopen("StationName.dat","rb");

fread(&h,sizeof(staname),1,fp);

while(h.k!

=0)

{

cout<k<<"号站----"<name<

iterP++;

if(iterP==p.end())break;

}

fclose(fp);

cout<

";

cin>>i;

if(i==1)

{

cout<<"请分别输入站号及站名(站号误重复)";

cin>>h.k>>h.name;

p.push_back(h);

iterP=p.begin();

fp=fopen("StationName.dat","wb");

while

(1)

{

h.k=iterP->k;

strcpy(h.name,iterP->name);

fwrite(&h,sizeof(staname),1,fp);

iterP++;

if(iterP==p.end())break;

}

h.k=0;

fwrite(&h,sizeof(staname),1,fp);

fclose(fp);

}

if(i==2){firstuse();p.clear();Loading2(p);}

if(i==3)break;

}

}

voidfirstuse()//站名数据文件初始化

{

stanamep;

p.k=0;

FILE*fp;

fp=fopen("StationName.dat","wb+");

fwrite(&p,sizeof(staname),1,fp);

fclose(fp);

}

voidLoading2(list&p)//读取站名链表数据

{

stanameh;

FILE*fp;

fp=fopen("StationName.dat","rb");

fread(&h,sizeof(staname),1,fp);

while(h.k!

=0)

{

p.push_back(h);

fread(&h,sizeof(staname),1,fp);

}

}

buy.cpp

#include"head.h"

voidprint(list&p)//显示乘车顺序

{

list:

:

iteratoriterP=p.begin();

inti=1;

cout<

"<

while(i)

{

cout<k<<"号站:

"<name;

iterP++;

if(i==5){cout<

if(!

(iterP==p.end()

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

当前位置:首页 > 高等教育 > 研究生入学考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1