数据结构讲义Word格式.docx

上传人:b****6 文档编号:21699341 上传时间:2023-01-31 格式:DOCX 页数:102 大小:149.37KB
下载 相关 举报
数据结构讲义Word格式.docx_第1页
第1页 / 共102页
数据结构讲义Word格式.docx_第2页
第2页 / 共102页
数据结构讲义Word格式.docx_第3页
第3页 / 共102页
数据结构讲义Word格式.docx_第4页
第4页 / 共102页
数据结构讲义Word格式.docx_第5页
第5页 / 共102页
点击查看更多>>
下载资源
资源描述

数据结构讲义Word格式.docx

《数据结构讲义Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构讲义Word格式.docx(102页珍藏版)》请在冰豆网上搜索。

数据结构讲义Word格式.docx

森林和二叉树的转换(A)

遍历树和森林(A)

7.图

图的有关概念

熟练掌握图的各种存储结构

图的遍历:

深度优先、广度优先(A)

最小生成树算法(两个)及其特点(A)

拓扑排序(A)

关键路径算法(A)

最短路径算法(两个)(A,O:

时间复杂度)

8.查找表

查找的有关概念,ASL等

顺序查找(A,P)

熟练掌握有序表的折半查找算法(A,P,C)

了解索引顺序表

熟练掌握二叉排序树的概念,建立(A),查找(A,P),删除(A),计算ASL(C)

平衡二叉排序树的概念,建立(A),判断失去平衡的类型,平衡化(A),计算ASL(C)

了解B_树,B+树的概念和特点

知道键树(数字查找树)

哈希表的概念、特点、构造哈希表(A),计算ASL和装填因子α(C)

了解各种查找表的性能(O)

9.内部排序

直接插入排序(A)

折半插入排序(A,P)

希尔排序(A)

起泡排序(A)

快速排序(A,P,O)

简单选择排序(P,A,O)

堆的概念,调整成堆(A),堆排序(A,O)

归并排序(A,O)

链式基数排序(A,O)

各种排序算法的对比结论(O)

第2章绪论

一、基础知识

概念和术语(黑体字部分)。

另外,注意:

1、数据元素是数据的基本单位。

P4

2、数据项是数据不可分割的最小单位。

P5

3、数据结构及其形式定义。

四种基本结构:

①集合②线性结构③树形结构④图(网)状结构

4、数据结构的

逻辑结构(抽象的,与实现无关)

物理结构(存储结构)顺序映像(顺序存储结构)位置“相邻”

非顺序映像(链式存储结构)指针表示关系P6

5、数据类型P7

抽象数据类型(ADT)P7

ADT=(数据对象,数据关系,基本操作)

ADT细分为原子类型,固定聚合,可变聚合类型。

P8

6、算法的概念P13

7、算法的五个特征

①有穷性②确定性③可行性④输入(0个或多个)⑤输出(1个或多个)

8、算法设计的要求:

①正确性②可读性③健壮性④效率与低存储量

其中正确性的四个层次(通常要求达到C层)。

9、算法的时间复杂度P15

常见有:

O

(1),O(n),O(n2),O(log2n),O(nlog2n),O(2n)

语句频度,用归纳法计算。

10、算法的空间复杂度P17

二、算法

起泡排序。

P16

另一种形式

voidBubbleSort(DataTypea[],intn)

{

for(i=0;

i<

n-1;

i++)

for(j=0;

j<

n-i-1;

j++)

if(a[j]>

a[j+1])

a[j]<

—>

a[j+1];

}

for(i=1;

n;

n-i;

if(a[j]>

i++){

change=fasle;

a[j+1]){

change=true;

}

if(!

change)break;

说明:

a)考试中要求写算法时,可用类C,也可用C程序。

b)尽量书写算法说明,言简意赅。

c)技巧:

用“边界值验证法”检查下标越界错误。

如上第一个:

第二个循环条件若写作j<

n-i,则当i=0时a[j+1]会越界。

d)时间复杂度为O(n2),第3个在最好情况下(待排记录有序),时间复杂度为O(n)。

三、习题

1.1编写冒泡排序算法,使结果从大到小排列。

1.2计算下面语句段中指定语句的频度:

1)for(i=1;

=n;

for(j=i;

x++;

//@

2)i=1;

while(i<

=n)

i=i*2;

第3章线性表

一、基础知识和算法

线性表及其特点

线性表是n个数据元素的有限序列。

线性结构的特点:

①“第一个”②“最后一个”③前驱④后继。

1.顺序表——线性表的顺序存储结构

特点

a)逻辑上相邻的元素在物理位置上相邻。

b)随机访问。

类型定义

简而言之,“数组+长度”。

constintMAXSIZE=线性表最大长度;

typedefstruct{

DataTypeelem[MAXSIZE];

intlength;

}SqList;

注:

a)SqList为类型名,可换用其他写法。

b)DataType是数据元素的类型,根据需要确定。

c)MAXSIZE根据需要确定。

constintMAXSIZE=64;

d)课本上的SqList类型可在需要时增加存储空间,在上面这种定义下不可以。

(这样做避免了动态内存分配,明显减少了算法的复杂程度,容易理解。

而且,原来Pascal版本的《数据结构》(严蔚敏)就是这样做的。

e)课本上的SqList类型定义中listsize表示已经分配的空间大小(容纳数据元素的个数)。

当插入元素而遇到L.length==L.listsize时,用realloc(L.elem,L.listsize+增量)重新分配内存,而realloc()函数在必要的时候自动复制原来的元素到新分配的空间中。

基本形态

顺序表空

0<

L.length<

MAXSIZE

条件L.length==0

不允许删除操作

顺序表满

条件L.length==MAXSIZE

不允许插入操作

不空也不满

可以插入,删除

基本算法——遍历

顺序访问所有元素

for(i=0;

L.length;

visit(L.elem[i]);

查找元素x

if(L.elem[i]==x)break;

if(i<

L.length)

找到;

else

未找到;

插入算法ListInsert(&

L,i,x)

前提:

表不满

合理的插入范围:

1≤i≤L.length+1

位序i在C/C++中对应于下标i-1。

步骤

第i至最后所有元素后移一个元素

在第i个位置插入元素x

表长增1

算法

boolListInsert(SqList&

L,inti,DataTypex)

if(L.length==MAXSIZE||i<

1||i>

L.length+1)returnfalse;

//失败

//元素后移

for(j=L.length-1;

j>

=i-1;

j--)//这里j为下标,从L.length-1到i-1

L.elem[j+1]=L.elem[j];

//若作为位序,有如何修改?

//插入x

L.elem[i-1]=x;

//表长增1

L.length++;

returntrue;

//插入成功

删除算法ListDelete(&

L,i,&

x)

表非空

合理的删除范围:

1≤i≤L.length

取出第i个元素

第i个元素之后的元素向前移动一个位置

表长减1

boolListDelete(SqList&

L,inti,DataType&

x)

if(L.length==0||i<

L.length)returnfalse;

x=L.elem[i-1];

L.elem[j-1]=L.elem[j];

L.length--;

//删除成功

算法分析

表2.1顺序表插入和删除算法的分析

插入

删除

基本操作

平均移动次数

移动元素

时间复杂度

O(n)

尾端操作

插入第n+1个元素,不移动

删除第n个元素,不移动

插入、删除需移动大量元素O(n);

但在尾端插入、删除效率高O

(1)。

其他算法

InitList(&

L),ClearList(&

L)

L.length=0;

ListEmpty(L)

returnL.length==0;

ListLength(L)

returnL.length;

GetElem(L,i,&

e)

e=L.elem[i-1];

2.单链表——线性表的链式存储结构之一

概念

线性链表,单链表,结点;

数据域,指针域;

头指针,头结点。

用指针表示数据之间的逻辑关系(逻辑相邻的元素物理位置不一定相邻)。

简而言之,“数据+指针”。

next

typedefstructLNode{

DataTypedata;

structLNode*next;

}LNode,*LinkList;

带头结点的单链表的基本形态有:

单链表空

...

条件:

L->

next==0

单链表不空

L->

next!

=0

基本算法(遍历)

借助指针,“顺藤摸瓜”(沿着链表访问结点)。

p=L->

next;

//注意起始位置的考虑

while(p!

=NULL){//判表尾,另外(p!

=0)或(p)均可

visit(p->

data);

//访问:

可以换成各种操作

p=p->

//指针沿着链表向后移动

例:

打印单链表中的数据。

voidPrintLinkList(LinkListL)

p=L->

while(p!

=NULL){

print(p->

//访问:

打印数据域

//在单链表L中查找元素x

//若找到,返回指向该结点的指针;

否则返回空指针

LinkListFind(LinkListL,DataTypex)

if(p->

data==x)returnp;

//找到x

returnNULL;

//未找到

//若找到,返回该元素的位序;

否则返回0

intFind(LinkListL,DataTypex)

j=1;

data==x)returnj;

j++;

//计数器随指针改变

return0;

前一个算法的另一种写法:

while(p&

&

p->

data!

=x)

if(p&

data==x)returnp;

elsereturn0;

或者

=x)p=p->

returnp;

//为什么

查找第i个元素

LinkListGet(LinkListL,inti)

while(p&

i){

if(p&

j==i)returnp;

elsereturn0;

查找第i-1个元素

p=L;

j=0;

i-1){

j==i-1)returnp;

技巧:

画图辅助分析。

思路:

先查找第i-1个元素

若找到,在其后插入新结点

boolListInsert(LinkList&

L,inti,DataTypex)

//查找第i-1个元素p

p=L;

//若找到,在p后插入x

j==i-1){

s=(LinkList)malloc(sizeof(LNode));

s->

data=x;

next=p->

//①

next=s;

//②

else

returnfalse;

//插入失败

注意:

a)要让p指向第i-1个而不是第i个元素(否则,不容易找到前驱以便插入)。

b)能够插入的条件:

p&

j==i-1。

即使第i个元素不存在,只要存在第i-1个元素,仍然可以插入第i个元素。

c)新建结点时需要动态分配内存。

若检查是否分配成功,可用

if(s==NULL)exit

(1);

//分配失败则终止程序

d)完成插入的步骤:

①②。

先修改新结点的指针域。

若找到且其后存在第i个元素,则用x返回数据,并删除之

boolListDelete(LinkList&

L,inti,int&

x)

//若存在第i个元素,则用x返回数据,并删除之

j==i-1&

next){//可以删除

s=p->

next=s->

x=s->

data;

free(s);

a)要求p找到第i-1个而非第i个元素。

为什么?

b)能够进行删除的条件:

next。

条件中的p->

next就是要保证第i个元素存在,否则无法删除。

若写成p->

next&

j==i-1也不妥,因为此时(循环结束时)可能有p==NULL,所以必须先确定p不空。

将条件中的“大前提”放在前面。

该条件也不可以写成p->

j==i-1,因为先有p!

=0才有p->

next,上式颠倒了这一关系。

c)释放结点的方法。

free(s);

d)完成删除的步骤:

建立链表的两种方法

建立空表(头结点);

依次插入数据结点(每次插入表尾得(a1,a2,…,an),每次插入表头得(an,…,a2,a1))。

顺序建表

voidCreateLinkList(LinkList&

L,intn)

//建立空表

L=(LinkList)malloc(sizeof(LNode));

next=NULL;

//空表

//用p指向表尾

//插入元素

scanf(x);

//插入表尾

p=s;

//新的表尾

逆序建表

//空表

//插入表头

next=L->

3.循环链表

最后一个结点的指针指向头结点。

L

同单链表。

空表:

next==L。

非空表。

与单链表的联系

判断表尾的方法不同:

单链表用p==NULL;

循环链表用p==L。

其余操作相同。

4.双向循环链表

一个结点包含指向后继(next)和指向前驱(prior)两个指针,两个方向又分别构成循环链表。

typedefstructDuLNode{

structDuLNode*prior,*next;

//两个指针

}DuLNode,*DuLinkList;

用后向指针判断L->

next==L,或者用前向指针判断L->

prior==L。

......

与单链表和循环链表的联系

最大不同:

前驱容易求得,可以向前遍历。

判断表尾的方法与循环链表相同:

p==L。

插入和删除时需要修改两个方向的指针。

插入和删除

需要修改两个方向的指针。

例如:

(见下表)

表2.2双向循环链表的插入和删除

p之后插入s

p之前插入s

删除p之后继s

删除p

s->

p->

prior=p;

next->

prior=s;

prior=p->

prior;

next=p;

prior->

s=p->

5.顺序表与单链表的比较

表2.3顺序表和单链表的比较

顺序表

单链表

以地址相邻表示关系

用指针表示关系

随机访问,取元素O

(1)

顺序访问,取元素O(n)

插入、删除需要移动元素O(n)

插入、删除不用移动元素O(n)(用于查找位置)

总结:

需要反复插入、删除,宜采用链表;

反复提取,很少插入、删除,宜采用顺序表。

二、习题

2.1将顺序表中的元素反转顺序。

2.2在非递减有序的顺序表中插入元素x,并保持有序。

2.3删除顺序表中所有等于x的元素。

2.4编写算法实现顺序表元素唯一化(即使顺序表中重复的元素只保留一个),给出算法的时间复杂度。

2.5非递减有序的顺序表元素唯一化(参见习题2.4),要求算法的时间复杂度为O(n)。

2.6将单链表就地逆置,即不另外开辟结点空间,而将链表元素翻转顺序。

2.7采用插入法将单链表中的元素排序。

2.8采用选择法将单链表中的元素排序。

2.9将两个非递减有序的单链表归并成一个,仍并保持非递减有序。

第4章栈和队列

1.栈

栈,栈顶,栈底,空栈,后进先出(LIFO),入栈(Push),出栈(Pop)。

顺序栈:

栈的顺序存储结构;

链栈:

栈的链式存储结构。

2.链栈

(1)存储结构

用不带头结点的单链表实现。

(2)类型定义

(3)基本形态

/\

栈空

条件:

S==NULL

栈非空

栈满(一般不出现)

(4)基本算法

入栈Push(&

s,x)

boolPush(LinkList&

s,DataTypex)

//新建结点

p=(LinkList)malloc(sizeof(LNode));

p)returnfalse;

//插入栈顶

s=p;

出栈Pop(&

s,&

栈非空。

boolPop(LinkList&

s,DataType&

if(s==NULL)returnfals

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

当前位置:首页 > 初中教育 > 英语

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

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