电子科大820数据结构考纲考点归纳Word文档格式.docx
- 文档编号:22825815
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:81
- 大小:840.93KB
电子科大820数据结构考纲考点归纳Word文档格式.docx
《电子科大820数据结构考纲考点归纳Word文档格式.docx》由会员分享,可在线阅读,更多相关《电子科大820数据结构考纲考点归纳Word文档格式.docx(81页珍藏版)》请在冰豆网上搜索。
加法原则:
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)<
O(n)<
O(nlogn)<
O(n2)<
O(n3)<
O(2n)<
O(n!
)<
O(nn)
空间复杂度:
算法所耗费的存储空间,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
ElemType*data;
intListSize,length;
*动态分配语句:
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
}//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中删除第i个元素,并用e返回其值
//i的合法值为1≤i≤L.length
if(i<
L.length)returnFALSE;
e=L.data[i-1];
for(intj=i;
j<
L.length;
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<
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++;
=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(尾插法):
voidCreateList2_L(LinkList&
//从表头到表尾正向输入n个元素的值,建立带头结点的单链表L
//每次均在表尾插入元素
q=L;
//表尾指针
for(i=n;
scanf(&
r->
r=p;
r->
//表尾指针置空
}//CreateList2_L
单链表的查找1(按位置查找):
LNode*GetElem_L(LinkListL,inti){
//L为带头结点的单链表的头指针
//当第i个元素存在时,返回第i个结点的指针,否则返回NULL
intj=1;
//计数,初始为1
p=L->
//初始化,p指向每一个结点
while(p&
i){//顺时针向后查找,直到p指向第i个元素或p为空
p=p->
j++;
if(!
p||j>
i)returnNULL;
//若i大于表长,p=NULL直接返回NULL
returnp;
//返回第i个结点的指针
}//GetElem_L
单链表的查找2(按值查找):
LNode*LocateElem_L(LinkListL,ElemTypee){
//当值查找成功时返回数据域值等于e的结点指针,否则返回NULL
inti=0;
data!
=e){//顺时针向后查找,直到p指向值为e的元素或p为空p=p->
//找到后返回该结点指针,否则返回NULL
}//LocateElem_L
插入操作(前插):
先找到前驱结点*p,然后完成在*p后插入*s,时间复杂度T(n)=O(n)
BOOLListInsert_L(LinkList&
//在带头结点的单链表L中第i个位置插入元素e
p=GetElem_L(L,i-1);
//查找插入位置的前趋结点
p)returnFALSE;
//插入位置不合法
s=(LinkList)malloc(sizeof(LNode));
//生成新结点
s->
data=e;
//插入L中
next=p->
p->
next=s;
}//ListInsert_L
插入操作(后插):
设p指向单链表中某结点,s指向待插入值为e的新结点,将*s插入到*p之后。
时间复杂度T(n)=O
(1)
//只给出关键代码段
s->
//修改指针域,顺序不能颠倒
e=p->
data;
//交换数据域部分
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指向其前趋
//删除位置不合法
q=p->
//令q指向被删除结点
next=q->
//将*q结点从链中断开
e=q->
//取其数据域的值
free(q);
//释放结点的存储空间
}//ListDelete_L
删除操作2:
将结点*p后继结点的值赋予其自身,然后删除后继结点,时间复杂度T(n)=O
(1)
q=p->
//修改指针域,顺序不能颠倒
data=p->
next->
//和后继结点交换数据域
//将*q结点从链中断开
//释放结点的存储空间
单链表的归并:
voidMergeList_L(LinkListLa,LinkListLb,LinkList&
//已知单链表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列
pa=La->
pb=Lb->
Lc=pc=La;
//用La的头结点作为Lc的头结点
while(pa&
pb){//开始归并
if(pa->
data<
=pb->
data){
pc->
next=pa;
pc=pa;
pa=pa->
}
else{
next=pb;
pc=pb;
pb=pb->
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
prior=s;
//语句执行顺序不唯一,但这两步必须在最后一步之前
prior=p;
//在结点*p之前插入值为e的新结点*s
prior;
prior->
双向链表的删除操作:
//删除结点*p的后继结点*q,并用e返回其值
e=q->
p->
q->
free(q);
//删除结点*q的前趋*p,并用e返回其值
e=p->
q->
next=q;
free(p);
带头结点的链表:
带头结点的链表结构定义:
typedefstructLNode{//结点类型
}*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=*--S.top;
//出栈时先取栈顶元素值,再将栈顶指针减1
栈的链式存储(链栈):
便于多个栈共享存储空间和提高其效率,不存在栈满上溢的情况,规定链栈没有头结点,Lhead指向栈顶元素。
S)//初始化
next=S->
S->
S,e)//入栈
p->
e)//出栈
p=S->
S->
DestroyStack(&
S)//销毁栈
p=S;
S=S->
队列的链式存储(链队列):
InitQueue(&
Q)//初始化
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
Q.front->
DestroyQueue(&
Q)//销毁队列
Q.rear=Q.front->
Free(Q.front);
Q.front=Q.rear;
EnQueue(&
Q,e)//入队
Q.rear->
Q.rear=p;
DeQueue(&
Q,&
e
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 电子科 820 数据结构 考点 归纳
![提示](https://static.bdocx.com/images/bang_tan.gif)