学习目标:
总复习数据结构:线性表
为备考划重点自用,不喜勿喷。
一、线性表的定义和基本操作
1.线性表是具有相同数据类型的n个数据元素的有限序列,其中n为表长,当n=0,是线性表是一个空表。
2.a1是表头元素,an是表尾元素。除第一个元素之外,每个元素有且仅有一个直接前驱;除最后一个元素外,每一个元素有且仅有一个直接后继。
二、线性表的顺序表示
1.顺序表的特点是表中元素的逻辑顺序与物理顺序相同。
2.顺序存储:
Loc(A):线性表存储的起始位置
数组下标 | 顺序表 | 内存地址 |
0 | a1 | Loc(A) |
1 | a2 | |
... | ... | ... |
n-1 | an | Loc(A)+(n-1)*sizeof(elemtype) |
... | ... | ... |
... | ... | ... |
maxsize-1 | ... | Loc(A)+(maxsize-1)*sizeof(elemtype) |
3.线性表静态分配:
typedef struct
{
elemtype data[maxsize];
int length;
}sqlist;
4.线性表动态分配
typedef struct
{
elemtype *data
int maxsize,length;
}seqlist;
5.顺序表最主要的特点是随机访问,即通过首地址和元素序号可在时间O(1)内找到指定的元素。
6.基本操作:
1)插入
bool insert(sqlist &L,int i,elemtype e)
{
if(i<1||i>L.length+1)
return false;
if(L.length>maxsize)
return false;
for(int j=L.length;j>=i;j--)//将第i个元素及之后的元素往后移
L.data[j]=L.data[j-1];
L.data[i-1]=e;//在位置i放e
L.length++;
return ture;
}
移动结点的平均次数为n/2
时间复杂度为O(n)
2)删除
代码略...
移动结点的平均次数为(n-1)/2
时间复杂度为O(n)
三、线性表的链式表示
1.头插法
Linklist headinsert(Linklist &L)
{
Linklist *s;
int x;
L=(Linklist *)malloc(sizeof(Linklist));//建立头节点
L->next=NULL;
scanf("%d",&x);
while(x!=9999)//头插法
{
s=(Linklist *)malloc(sizeof(Linklist));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
2.尾插法
Linklist tailinsert(Linklist &L)
{
Linklist *s;
Linklist *end=L;//表尾指针
int x;
L=(Linklist *)malloc(sizeof(Linklist));//建立头节点
L->next=NULL;
scanf("%d",&x);
while(x!=9999)//头插法
{
s=(Linklist *)malloc(sizeof(Linklist));
s->data=x;
end->next=s;
end=end->next;
scanf("%d",&x);
}
end->next=NULL;//表尾指针置空
return L;
}
3.按值查找的时间复杂度为O(n)。
4.双链表的结点类型
typedef struct Dnode
{
elemtype data;
struct Dnode *prior,*next;//前驱和后继指针
}Dnode,*Dlinklist;
5.循环链表和单链表的区别在于:表中的最后一个结点的指针不是NULL,而改为指向头结点。
6.循环单链表可以从表中任意一个结点开始遍历整个链表。
7.循环双链表
8.顺序表与链表的区别:采用顺序存储时,逻辑上相邻的元素,对应的物理存储位置也相邻;采用链式存储时,物理存储位置不一定相邻,对应的逻辑关系是通过指针链接来表示的。
四、习题
1.一个具有n个结点的单链表,在指针p所指结点后插入一个新结点的时间复杂度为();在给定值为x的结点后插入一个新结点的时间复杂度为()。
【解答】Ο(1),Ο(n)
【分析】在p所指结点后插入一个新结点只需修改指针,所以时间复杂度为Ο(1);而在给定值为x的结点后插入一个新结点需要先查找值为x的结点,所以时间复杂度为Ο(n)。
2.若某线性表中最常用的操作是取第i 个元素和找第i个元素的前趋,则采用()存储方法最节省时间。
A顺序表 B单链表 C双链表 D 单循环链表
【解答】A
【分析】线性表中最常用的操作是取第i 个元素,所以,应选择随机存取结构即顺序表,同时在顺序表中查找第i个元素的前趋也很方便。单链表和单循环链表既不能实现随机存取,查找第i个元素的前趋也不方便,双链表虽然能快速查找第i个元素的前趋,但不能实现随机存取。
3.若链表中最常用的操作是在最后一个结点之后插入一个结点和删除最后一个结点,则采用()存储方法最节省运算时间。
A单链表 B循环双链表 C单循环链表 D带尾指针的单循环链表
【解答】B
【分析】在链表中的最后一个结点之后插入一个结点需要知道终端结点的地址,所以,单链表、单循环链表都不合适,删除最后一个结点需要知道终端结点的前驱结点的地址,所以,带尾指针的单循环链表不合适,而循环双链表满足条件。
4.将两个长度分别为m和n的递增有序链表,归并成一个按元素递减有序的单链表,可能达到的最好的时间复杂度是( ).
【解答】O(m+n)
5.假设有两个按元素递增有序排列的线性表 A 和 B,均以带头结点的链表作为存储结构,编写算法,将 A 表和 B 表归并成一个按元素递减有序排列的线性表 C,并要求利用原表(A 表和B 表)的结点空间存放表 C。
【解答】