赞
踩
王道中这章主讲了线性表的定义、基本操作、顺序表示、链式表示。下方内容主分了文字部分和代码部分,便于记忆和整理。
在901中这章的要求集中在链表的基础操作中,应用题大概会出问答题。
【当前每一小节的应用题待做,先把选择题过完,整本书预计1个月。每日15-20页】
7.31 | 15-30页:线性表、顺序表+练习题 |
---|---|
8.1 | 31-45页:单链表、双链表、循环链表、静态链表 |
8.2 | 46-62页:链表部分35道选择题review |
存取方式 | |
---|---|
逻辑结构和物理结构 | |
插入、查找、删除操作 | |
空间分配 |
存取方式 | 顺序表顺序存取也可以随机存取;链表只能从表头开始依次顺序存取。 |
---|---|
逻辑结构和物理结构 | 顺序表中,逻辑上相邻的两个元素,对应的物理结构也相邻;链表就不一定了,其对应的逻辑关系是通过指针链表来表示的。 |
插入、查找、删除操作 | 按值查找:顺序表无序,O(n),有序时,O(logn)【二分法】;按位置查找:顺序表支持随机访问O(1),链表的平均时间复杂度为O(n)。删除插入:顺序表移动半个表长的元素,链表只需要修改相关节点的指针域即可。 |
空间分配 | 顺序存储在静态分配的情况下,装满就不能扩充,若再加入新元素,就会内存溢出,因此需要实现分配足够大的存储空间,这个很难把控,过大造成闲置,过小造成溢出;顺序表的动态存储虽然存储空间可以扩充,但需要移动大量元素,造成操作效率降低,而且若内存中没有更大块的连续存储空间,会导致分配失败;链表存储的节点空间只在需要时申请分配,操作灵活、高效。由于链表的每个结点都需要指针域,存储密度不够大。 |
【错误答案】A or C
【思路】随机存取:可以直接通过地址或下标在常数时间内访问数据的存取方式。而且,线性表 顺序存储结构使用数组实现,所以是 可以随机存取的存储结构;
【补充】
索引存取:通过索引(类似目录或指针)来查找和访问数据的存取方式。e.g.数据库的索引、B树、B+树、哈希表。
链式结构应该是顺序存取的存储结构;
【错误答案】A
【思路】随机存取:和下标有关的选项 肯定是和n无关 所以BD先排除 A :需要遍历整个顺序表 因为不能根据值索引 C:正确 故C
【错误答案】A
【思路】
Ⅰ SeqList.data[i] SeqList.data[i-1]
Ⅱ len <= MaxSize 时 data[len] = newnode
Ⅲ 需要移动后面len-1个结点往前移位 和n有关
Ⅳ 移动len-i个节点 和n有关
所以ⅠⅡ时间复杂度O(1) 选C
【错误答案】A
【思路】顺序表的效率高于链表:随机存取
Ⅰ 符合随机存取的能力,链表还需要顺序查找到指向i结点的指针才能输出它的数据域
Ⅱ 交换值,虽然交换动作二者比较不出,但是链表还需要将指针移动到位置3所以还是顺序表效率高
Ⅲ 二者都需要遍历,差不太多。所以C
做题的时候确实已经可以直接把我脑子入土了,错了好多,没事巩固的知识也多
【错误答案】C
【思路】 结点内的存储单元地址≠结点的存储空间
结点内的存储单元地址是指:在每个节点内部,数据域和指针域的存储单元地址,肯定是连续的。所以A
结点的存储空间是不连续的。链式存储:链表 逻辑顺序和物理位置不一致
【错误答案】B
【思路】
Ⅰ顺序存储结构直接理解为数组,也可以链式结构吧 静态链表 ×
Ⅱ 删除表尾元素,需要知道这个尾结点的前驱结点,但在单链表中需要遍历,所以还是和表长有关的 ×
Ⅲ 带头节点的单循环链表为空表时head指向自己
Ⅳ 对,我当时好像想成了数组可以折半查找所以O(logn)
Ⅴ 队列 先进先出原则 进:头插法 出:应该是带尾指针的循环双链表吧,不然尾结点的前驱找不到哇 ×
判断完了,才发现如果Ⅱ不对,那只能选BCD Ⅴ肯定对 所以D
【补充知识】循环单链表表示队列:对Ⅴ的判别错误,是对单链表实现队列 分析有误:
【错误答案】B
【思路】有序单链表,首先将一维数组有序的话是O(nlogn)各种排序一般好像是快速排序,然后分配空间建立链表O(n)所以D
【错误答案】C or B 选了B 我感觉C太笼统了:)
【思路】记住就好,不增加头结点也会标识出结点中首结点的位置,所以C。单链表中增加一个头结点的目的是方便运算的实现。
【错误答案】B
【思路】读题啊大哥 线性表:所以分为链表和顺序表 如果顺序表 50 链表 0 所以D
【错误答案】D 无语死了
【思路】有序单链表插入一个新结点,最低 头部 O(1) 最高 尾部 O(n) 所以B
【错误答案】D
【思路】循环单链表 欸 为空表 head->next == head 所以?头结点的指针域与L的值相等
【错误原因】L *L分别不清楚
【错误答案】C
【思路】末尾插入结点:能快速指向尾部就节省时间,尾指针或者循环+头指针; 删除结点:能够随时遍历整个链表 ,要求最节省时间:方便找前驱,所以A
【错误答案】D
【思路】头尾相接的时间复杂度为O(1) 循环单链表 前一个链表的尾部改为指向后一个链表的头部 后一个链表的尾部改为指向前一个链表的头部。所以,都指向尾部比较合适,因为都要改变他们的尾部结点指向,所以B。
【错误答案】B
【思路】看下图思路 选D
【错误答案】B
【思路】看下图所以选C
注意:一般可以忽略边界条件判断,变量定义内存分配等细节,主要体现算法思想。所以这里更要多过几遍,以防考场上对于细节过于细究或者模糊浪费时间。纸质考试≠上机考!!!
#define MaxSize 50
typedef struct {
ElemType data[MaxSize]; // 顺序表的元素
int length; //顺序表当前长度
}SqList;//顺序表类型定义
#define InitSize 100
typedef strcut{
ElemType *data;//动态分配数组的指针
int MaxSize,length;//数组的最大容量和当前个数
}SeqList;
//C ++ 动态分配语句
L.data = new ElemType(InirSize);
//C 动态分配语句
L.data =(ElemType*)malloc(sizeof(ElemType)*InitSize);
静态只需要设置length 动态对maxsize length data都需要进行设置或分配。
//声明一个顺序表SqList 静态分配
void InitList (SqList &L){
L.length = 0;
}
//动态分配
void InitList(SeqList &L){
L.data = (ElemType*)malloc(sizeof(ElemType)*MaxSize);
L.length = 0;
L.MaxSize = InitSize;
}
已知:顺序表L 新元素e 插入为序i ----> 数组下标为i-1【如果搞不清,则判断插入位置是否合法和for循环细节上就会搞错】
bool ListInsert(SqList &L, int i, ElemType e) { // 判断i是否有效,i的取值范围应该在1到L.length+1之间 if (i < 1 || i > L.length + 1) { // 插入位置不合法 return false; } // 当前存储空间已满 if (L.length >= MaxSize) { return false; } // 从最后一个元素开始,依次向后移动,直到第i个位置 for (int j = L.length; j >= i; --j) { L.data[j] = L.data[j - 1]; } // 在第i个位置插入新元素 L.data[i - 1] = e; // 长度加1 L.length++; return true; }
已知:顺序表 删除位置 删除元素的返回
bool ListDelete(SqList &L , int i , ElemType &e){
//判断i
if(i < 0 || i > L.length) return false;
//不用判断当前长度
e = L.data[i-1];
for(int j = i-1 ; j < L.length-1; j++){
L.data[j] = L.data[j+1];//j+1不能越界 越length
}
L.length--;
return true;
}
已知:顺序表 查找元素 返回位序
int LocateElem(SqList &L , ElmeType e){
int i;
for(i = 0 ; i < L.length ; i++){
if(L.data[i] == e) return i+1;
}
return 0;
}
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode , *LinkList;
bool InitList(LinkList &head){
head = (LNode*)malloc(sizeof(LNode));
head->next = NULL;
return true;
}
bool InitList(LinkList &head){
head = NULL;
return true;
}
//带头结点 int Length(LinkList L){ int len = 0; LNode *p = L->next; while(p){ p=p->next; len ++; } return len; } or int Length(LinkList L){ int len = 0; LNode *p = L; while(p->next){ p = p->next; len++; } return len; }
已知:L、第i个结点 如果i超过了表长返回NULL【书中写的小于表长???那不就可以找到的吗】
LNode *GetElem(LinkList L , int i){
LNode *p = L;
int j = 0;
while(p != NULL && j < i){//我写成了p->next && j<i 错的家人们!!
p=p->next;
j++;
}
return p;
}
已知:给定值e 当没有这个值返回NULL
LNode *LocateElem(LinkList head , ElemType e){
LNode *p = head->next;
while( p != NULL && p->data != e){
p = p->next;
}
return p;
}
已知:L、第i个结点处插入、data 为 e
bool ListInsert(LinkList &head , int i , ElemType e){ LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = e; //移动到i-1的位置 LNode *p = head; int j = 0; while(p != NULL && j<i-1){ p = p->next; } //!!!!!!判定i是否合法 if(p == NULL) return false; //插入结点 newNode->next = p->next; //颠倒的话需要多增加一个指针变量存储被覆盖的p->next; p->next = newNode; return true; }
前插操作,是p在位置i处的这个结点之前插入newNode.书上的思路结点上仍然是后插操作,结束后将newNode与p内的数据域进行交换。
已知:L、位置i、要返还的ElemType e
bool ListDelete(LinkList &head , int i, ElemType &e){ LNode *p = head; //移动至i-1处 int j = 0; while(p != NULL && j<i-1){ p = p->next; j++; } //判定i是否合法 比【插入】多一个条件 if(p ==NULL || p->next ==NULL)return false; //删除操作 因为要释放被删除结点 所以新开一个指针 LNode *q = p->next; e = q->data; p->next = q->next; free(q); return true; }
扩展不知道他在干啥,遇到了再说吧【坑 located in 电子版48页】
LinkList List_HeadInsert(LinkList &head){
LNode *newNode ; int x;
head = (LNode*)malloc(sizeof(LNode));
head->next = NULL;
scanf("%d",&x);
while(x != 9999){//输入9999表示结束
newNode = (LNode*)malloc(sizeof(LNode));
newNode->next = head->next;
newNode->data = x;
head->next = newNode;
scanf("%d" ,&x);
}
return head;
}
LinkList List_TailInsert(LinkList &head){ LNode *newNode; int x; head = (LNode*)malloc(sizeof(LNode)); head->next = NULL; LNode *p = head;//尾指针 scanf("%d",&x); while(x!=9999){ newNode = (LNode*)malloc(sizeof(LNode)); newNode->next = NULL; newNode->data = x; p->next = newNode; p = p->next; scanf("%d" ,&x); } return head; }
书上
LinkList List_TailInsert(LinkList &L){
int x;
L = (LNode*)malloc(sizeof(LNode));
LNode *s , *r;//r为尾指针 s为新结点
scanf("%d" ,&x);
while(x!=9999){
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d",&x);
}
r->next = NULL;
return L;
}
要疯了本来以为就结束了结果才到35!!!!
typedef struct DNode{
ElemType data;
strcut DNode *prior;
strcut DNode *next;
}DNode, *DLinkList;
p->next->prior = s;
s->prior = p;
s->next = p->next;
p->next = s;
q->next->prior = p;
p->next = q->next;
free(q);
以next == -1 作为其结束的标志。删除插入与动态一致,只需要修改指针,不需要移动元素,没有单链表方便。
#define MaxSize 50
typedef struct {
ElemType data;
int next;
}SLinkList(MaxSize);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。