电子科大820数据结构考纲考点归纳.docx

上传人:b****8 文档编号:9650884 上传时间:2023-02-05 格式:DOCX 页数:81 大小:840.93KB
下载 相关 举报
电子科大820数据结构考纲考点归纳.docx_第1页
第1页 / 共81页
电子科大820数据结构考纲考点归纳.docx_第2页
第2页 / 共81页
电子科大820数据结构考纲考点归纳.docx_第3页
第3页 / 共81页
电子科大820数据结构考纲考点归纳.docx_第4页
第4页 / 共81页
电子科大820数据结构考纲考点归纳.docx_第5页
第5页 / 共81页
点击查看更多>>
下载资源
资源描述

电子科大820数据结构考纲考点归纳.docx

《电子科大820数据结构考纲考点归纳.docx》由会员分享,可在线阅读,更多相关《电子科大820数据结构考纲考点归纳.docx(81页珍藏版)》请在冰豆网上搜索。

电子科大820数据结构考纲考点归纳.docx

电子科大820数据结构考纲考点归纳

ch1.数据结构及算法的相关概念和术语

(1)数据结构及算法的概念;

数据:

所有能输入到计算机中并被计算机程序处理的符号的总称。

数据元素:

数据的基本单位,一个数据项可由若干个数据项组成。

数据项:

构成数据元素的不可分割的最小单位。

*关系:

数据>数据元素>数据项

数据对象:

性质相同的数据元素的集合。

数据类型:

原子类型、结构类型、抽象数据类型。

数据结构:

相互之间存在一种或多种特定关系的数据元素的集合。

(2)数据的逻辑结构和存储结构;

数据结构三要素:

数据的逻辑结构、数据的存储结构、数据的运算

数据的逻辑结构:

线性结构(线性表)、非线性结构(集合、树和图)。

数据的存储结构:

顺序存储:

优点:

可以随机存取,每个元素占用最少存储空间

缺点:

可能产生较多碎片现象

链式存储:

优点:

不会出现碎片现象

缺点:

每个元素占用较多存储空间,只能实现顺序存储

索引存储:

优点:

检索速度快

缺点:

增加了附加的索引表,会占用较多存储空间

散列存储:

优点:

检索、增加和删除结点的操作都很快

缺点:

可能出现存储单元的冲突,解决冲突会增加时间和空间的开销

(3)算法的定义及特性;

算法:

对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。

算法的特性:

有穷性、确定性、可行性、输入、输出

算法设计的要求:

正确性、可读性、健壮性、效率与低存储量需求

*同一个算法,实现语言的级别越高,执行效率就越低

(4)算法时间复杂度和空间复杂度的分析方法。

时间复杂度:

主要分析语句频度(一条语句在算法中被重复执行的次数)之和T(n)的数量级

加法原则:

T(n)=T1(n)+T2(n)=O(max(f(n),g(n)))

乘法原则:

T(n)=T1(n)∙T2(n)=O(f(n)·g(n))

*常见时间复杂度比较:

O

(1)

空间复杂度:

算法所耗费的存储空间,S(n)=O(g(n))

算法原地工作是指算法所需辅助空间是常量,即O

(1)

ch2.线性表

(1)线性表的定义

线性表:

具有相同数据类型的n(n≥0)个数据元素的有限序列,一般表示如下:

L=(a1,a2,…,ai+1,…,an)

其中,a1是唯一的“第一个”数据元素,称为表头元素;an是唯一的“最后一个”数据元素,称为表尾元素;除第一个元素外,每个元素有且仅有一个直接前趋;除最后一个元素外,每个元素有且仅有一个直接后继。

线性表的特点:

表中元素具有逻辑上的顺序性,表中元素都是数据元素,表中元素的数据类型都相同,表中元素具有抽象性。

(2)线性表的基本操作及在顺序存储及链式存储上的实现;

线性表的基本操作:

InitList(&L)构造一个空的线性表

ListLength(L)求表长,即求线性表中数据结点(如果是带头结点单链表,则不含头结点)的个数

LocateElem(L,e)按值查找

GetElem(L,i)按位查找

ListInsert(&L,i,e)在表L中的第i个位置插入指定元素

ListDelete(&L,i,&e)删除表L中的第i个位置的元素,并输出其值

PrintList(L)按前后顺序输出线性表L的所有元素值

ListEmpty(L)判空,若L为空表,返回TRUE,否则返回FALSE

DestroyList(&L)销毁线性表,并释放表L占用的内存空间

ClearList(&L)将L重置为空表

PriorElem(L,cur_e,&pre_e)若cur_e是表L的数据元素,且不是第一个,用pre_e返回其前驱NextElem(L,cur_e,&next_e)若cur_e是表L的元素,且不是最后一个,用next_e返回其后继

ListTraverse(L,visit())表的遍历,即依次对L的每个元素调用函数visit()

线性表的顺序存储(顺序表):

线性表中第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间关系:

LOC(ai+1)=LOC(ai)+l

线性表的第i个数据元素ai的存储位置:

LOC(ai)=LOC(a1)+(i-1)·l

顺序表的特点:

可以进行随机存取,即通过首地址和元素序号可以在O

(1)的时间内找到指定元素,但插入和删除元素操作需要移动大量元素

顺序表结构的定义:

顺序表的静态分配:

#defineMaxSize50

typedefstruct{

ElemTypedata[MaxSize];

intlength;

}SqList;

顺序表的动态分配:

#defineInitSize50

typedefstruct{

ElemType*data;

intListSize,length;

}SqList;

*动态分配语句:

L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);

顺序表基本操作的实现:

初始化操作:

构造一个空的顺序表L

BOOLInitList_Sq(SqList&L){

L.data=(ElemType*)malloc(InitSize*sizeof(ElemType));

if(!

L.data)exit(OVERFLOW);

L.length=0;

L.ListSize=InitSize;

returnTRUE;

}//InitList_Sq

插入操作:

在第i(1≤i≤n)个元素之前插入一个元素,需将第n至第i(共n-i+1)个元素向后移动一个位置。

BOOLListInsert_Sq(SqList&L,inti,ElemTypee){

//在顺序表L中的第i个位置插入新元素e

//i的合法值为1≤i≤L.length+1

if(i<1||i>L.length+1)returnFALSE;//i值不合法

if(L.length>=ListSize){//当前存储空间已满,不能插入

returnFALSE;

for(i=L.length;j>=i;j--)//将第i个位置及之后元素后移

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

L.data[i-1]=e;//在位置i处放入e

L.length++;//表长加1

returnTRUE;

}//ListInsert_Sq

时间复杂度:

最好情况:

在表尾插入,无须移动元素,T(n)=O

(1)

最坏情况:

在表头插入,需要移动第一个元素后面所有元素,T(n)=O(n)

平均情况:

T(n)=n/2=O(n)

删除操作:

在顺序表L中删除第i(1≤i≤n)个元素,需将第n至第i(共n-i+1)个元素向前移动一个位置。

BOOLListDelete_Sq(SqList&L,inti,ElemTypee){

//在顺序表L中删除第i个元素,并用e返回其值

//i的合法值为1≤i≤L.length

if(i<1||i>L.length)returnFALSE;//i值不合法

e=L.data[i-1];

for(intj=i;j

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

L.length--;

returnTRUE;

}//ListDelete_Sq

时间复杂度T(n):

最好情况:

删除表尾元素,无须移动元素,T(n)=O

(1)

最坏情况:

删除表头元素,需要移动第一个元素后面所有元素,T(n)=O(n)

平均情况:

T(n)=(n-1)/2=O(n)

按值查找(顺序查找):

intLocateElem(SqListL,inti,ElamTypee){

//查找顺序表中值为e的元素,若查找成功,返回元素位序,否则返回0

for(inti=0;i

if(L.data[i]==e)returni+1;//下标为i的元素值等于e,返回其位号i+1

}

return0;

}//LocateElem

顺序表的归并:

T(n)=O(La.length+Lb.length)

voidMergeList_Sq(SqListLa,SqListLb,SqList&Lc){

//已知顺序表La和Lb的元素按值非递减排列

//归并La和Lb得到新的顺序表Lc,Lc的元素也按值非递减排列

pa=La.data;

pb=Lb.data;

Lc.ListSize=Lc.length=La.length+Lb.length;

pc=Lc.data=(ElemType*)malloc(Lc.ListSize*sizeof(ElemType));

if(!

Lc.data)exit(OVERFLOW);

pa_last=La.data+La.length-1;

pb_last=Lb.data+Lb.length-1;

while(pa<=pa_last&&pb<=pb_last){//开始归并

if(*pa<=*pb)*pc++=*pa++;

else*pc++=*pb++;

}

while(pa<=pa_last)*pc++=*pa++;

while(pb<=pb_last)*pc++=*pb++;

}//MergeList_Sq

线性表的链式存储(单链表):

单链表结构的定义:

typedefstructLNode{

Elemtypedata;

structLNode*next;

}LNode,*LinkList;

引入头结点的单链表:

头结点的数据域可以不设任何信息,也可以记录表长等信息,头结点的指针域指向线性表的第一个结点。

*引入头结点的两个优点:

(1)由于开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作就和在表的其它位置上操作一致,无须进行特殊处理

(2)无论链表是否为空,其头指针是指向头结点的非空指针(空表中头结点的指针域空),因此空表和非空表的处理也就统一了

单链表基本操作的实现:

单链表的建立1(头插法):

时间复杂度O(n)

voidCreateList1_L(LinkList&L,intn){

//从表尾到表头逆位序输入n个元素的值,建立带头结点的单链表L

//每次均在头结点之后插入元素

L=(LinkList)malloc(sizeof(LNode));//创建头结点

L->next=NULL;//初始为空表

for(i=n;i>0;i--){

p=(LinkList)malloc(sizeof(LNode));//创建新结点

scanf(&p->data);

p->next=L->next;

L->next=p;//将新结点插入表中

}

}//CreateList1_L

单链表的建立2(尾插法):

时间复杂度O(n)

voidCreateList2_L(LinkList&L,intn){

//从表头到表尾正向输入n个元素的值,建立带头结点的单链表L

//每次均在表尾插入元素

L=(LinkList)malloc(sizeof(LNode));//创建头结点

L->next=NULL;//初始为空表

q=L;//表尾指针

for(i=n;i>0;i--){

p=(LinkList)malloc(sizeof(LNode));//创建新结点

scanf(&p->data);

r->next=p;

r=p;//将新结点插入表中

}

r->next=NULL;//表尾指针置空

}//CreateList2_L

单链表的查找1(按位置查找):

LNode*GetElem_L(LinkListL,inti){

//L为带头结点的单链表的头指针

//当第i个元素存在时,返回第i个结点的指针,否则返回NULL

intj=1;//计数,初始为1

p=L->next;//初始化,p指向每一个结点

while(p&&j

p=p->next;

j++;

}

if(!

p||j>i)returnNULL;//若i大于表长,p=NULL直接返回NULL

returnp;//返回第i个结点的指针

}//GetElem_L

单链表的查找2(按值查找):

LNode*LocateElem_L(LinkListL,ElemTypee){

//L为带头结点的单链表的头指针

//当值查找成功时返回数据域值等于e的结点指针,否则返回NULL

inti=0;

p=L->next;

while(p&&p->data!

=e){//顺时针向后查找,直到p指向值为e的元素或p为空p=p->next;

}

returnp;//找到后返回该结点指针,否则返回NULL

}//LocateElem_L

插入操作(前插):

先找到前驱结点*p,然后完成在*p后插入*s,时间复杂度T(n)=O(n)

BOOLListInsert_L(LinkList&L,inti,ElemTypee){

//在带头结点的单链表L中第i个位置插入元素e

p=GetElem_L(L,i-1);//查找插入位置的前趋结点

if(!

p)returnFALSE;//插入位置不合法

s=(LinkList)malloc(sizeof(LNode));//生成新结点

s->data=e;//插入L中

s->next=p->next;

p->next=s;

returnTRUE;

}//ListInsert_L

插入操作(后插):

设p指向单链表中某结点,s指向待插入值为e的新结点,将*s插入到*p之后。

时间复杂度T(n)=O

(1)

//只给出关键代码段

s->next=p->next;//修改指针域,顺序不能颠倒

p->next=s;

e=p->data;//交换数据域部分

p->data=s->data;

s->data=e

删除操作1:

先找到被删结点的前趋,然后完成在*p后删除被删结点,时间复杂度T(n)=O(n)

BOOLListDelete_L(LinkList&L,inti,ElemType&e){

//在带头结点的单链表L中,删除第i个元素,并由e返回其值

p=GetElem_L(L,i-1);//查找第i个结点,并令p指向其前趋

if(!

p)returnFALSE;//删除位置不合法

q=p->next;//令q指向被删除结点

p->next=q->next;//将*q结点从链中断开

e=q->data;//取其数据域的值

free(q);//释放结点的存储空间

returnTRUE;

}//ListDelete_L

删除操作2:

将结点*p后继结点的值赋予其自身,然后删除后继结点,时间复杂度T(n)=O

(1)

//只给出关键代码段

q=p->next;//修改指针域,顺序不能颠倒

p->data=p->next->data;//和后继结点交换数据域

e=p->data;

p->next=q->next;//将*q结点从链中断开

free(q);//释放结点的存储空间

单链表的归并:

voidMergeList_L(LinkListLa,LinkListLb,LinkList&Lc){

//已知单链表La和Lb的元素按值非递减排列

//归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列

pa=La->next;

pb=Lb->next;

Lc=pc=La;//用La的头结点作为Lc的头结点

while(pa&&pb){//开始归并

if(pa->data<=pb->data){

pc->next=pa;

pc=pa;

pa=pa->next;

}

else{

pc->next=pb;

pc=pb;

pb=pb->next;

}

}

pc->next=pa?

pa:

pb;//插入剩余段

free(Lb);//释放Lb头结点

}//MergeList_L

(3)各种变形链表(循环链表、双向链表、带头结点的链表等)的表示和基本操作的实现;

循环链表:

循环单链表:

表尾结点的next域指向L,表中没有指针域为NULL的结点,因此循环单链表的判空条件是看它的头结点的指针域是否等于头指针;循环单链表在任何一个位置上插入和删除操作都是等价的,无需判断是否表尾;循环单链表可以从表中任一结点开始遍历整个链表。

循环单链表不设头指针而只设尾指针,可使一些操作效率更高。

循环双链表:

与循环单链表不同的是,循环双链表中头结点的prior指针还指向表尾结点;在循环双链表L中,某结点*p为尾结点时,p->next==L;当循环双链表为空时,对其头结点*p,有p->prior=p->next==L。

双向链表:

其结点有两个指针域,一个指向直接后继,另一个指向直接前趋,双向链表的插入、删除结点算法的时间复杂度为O

(1)。

双向链表结构的定义:

typedefstructDuLNode{

ElemTypedata;

structLNode*prior,*next;

}DuLNode,*DuLinkList;

双向链表的插入操作:

//只给出关键代码段

//在结点*p之后插入值为e的新结点*s

s->data=e;

s->next=p->next;

p->next->prior=s;//语句执行顺序不唯一,但这两步必须在最后一步之前

s->prior=p;

p->next=s;

//在结点*p之前插入值为e的新结点*s

s->data=e;

s->prior=p->prior;

p->prior->next=s;

s->next=p;

p->prior=s;

双向链表的删除操作:

//只给出关键代码段

//删除结点*p的后继结点*q,并用e返回其值

e=q->data;

p->next=q->next;

q->next->prior=p;

free(q);

//删除结点*q的前趋*p,并用e返回其值

e=p->data;

q->prior=p->prior;

p->prior->next=q;

free(p);

带头结点的链表:

带头结点的链表结构定义:

typedefstructLNode{//结点类型

ElemTypedata;

structLNode*next;

}*Link,*Position;

typedefstruct{//链表类型

Linkhead,tail;//分别指向链表的头结点和尾结点

intlength;//线性表中元素的个数

}LinkList;

ch3.栈与队列

(1)栈和队列的基本概念;栈和队列的顺序存储结构、链式储存结构及其存储特点;

栈:

限定在表尾进行插入或删除操作(头进尾出)的线性表,表尾称为栈顶(top),表头称为栈底(bottom),不含任何元素的栈称为空栈,栈又被称为后进先出(LIFO)线性表。

队列:

只允许在表的一端进行插入,另一端进行删除操作(尾进头出),允许插入的一端叫做队尾(rear),允许删除的一端叫做队头(front),是一种先进先出(FIFO)的线性表。

栈的基本操作:

InitStack(&S)初始化,构造一个空栈S

StackEmpty(S)栈S判空

StackLength(S)求栈长,即栈S的元素个数

Push(&S,x)入栈,插入元素为x的新栈顶元素

Pop(&S,x)出栈,删除栈S的栈顶元素,并用x返回其值

GetTop(S,&x)取栈顶,用x返回栈S的栈顶元素

ClearStack(&S)将栈S清空

DestroyStack(&S)销毁栈,并释放其存储空间

栈的顺序存储(顺序栈):

可能发生上溢

基本操作:

//只给出关键语句

InitStack(&S)//栈满条件S.top-S.base=S.StackSize

S.top=S.base;S.StackSize=InitSize;//栈空条件S.top==S.base

GetTop(S,&e)

e=*(S.top-1);

Push(&S,e)

*S.top++=e;//入栈时栈顶指针先加1,再送值到栈顶元素

Pop(&S,&e)

e=*--S.top;//出栈时先取栈顶元素值,再将栈顶指针减1

栈的链式存储(链栈):

便于多个栈共享存储空间和提高其效率,不存在栈满上溢的情况,规定链栈没有头结点,Lhead指向栈顶元素。

基本操作:

//只给出关键语句

InitStack(&S)//初始化

p->next=S->next;S->next=p;

Push(&S,e)//入栈

p->data=e;S->next=p;p->next=S->next;

Pop(&S,&e)//出栈

p=S->next;e=p->data;S->next=p->next;free(p);

DestroyStack(&S)//销毁栈

p=S;S=S->next;free(p);

队列的链式存储(链队列):

基本操作:

//只给出关键语句

InitQueue(&Q)//初始化

Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));Q.front->next=NULL;

DestroyQueue(&Q)//销毁队列

Q.rear=Q.front->next;Free(Q.front);Q.front=Q.rear;

EnQueue(&Q,e)//入队

p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;

DeQueue(&Q,&e

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

当前位置:首页 > 求职职场 > 简历

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

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