选择题
[2019年第2题]. A
[2020年第2题]. A
[2020年第3题]. A
[2021年第1题]. B
[2021年第2题]. A
[2021年第3题]. A
[2022年第2题]. B
[2022年第3题]. B
[2023年第2题]. D
算法题
[2019年第1题].
//方法一
bool InsertOrderList(SqList &L, ElemType e) {
//题目要求:顺序表,按照递增排序,我需要把元素e插入L适当位置,使得顺序表依然保持有序
//思路:从前往后遍历顺序表,找到第一个比e大的元素的位置idx,然后再把idx以及后面的元素全部后移,把新添加的元素e放到idx
if(L.length >= MaxSize) return false; //说明顺序表已满
int idx = -1;
int ptr = 0;
while(ptr < L.length) { //找到比e大的元素的下标
if(L.elem[ptr] > e) {
idx = ptr;
break;
}
ptr++;
}
//说明L.elem中的元素都比e小
if(idx == -1) idx = L.length;
//把idx以及后面的元素全部往后移动一个位置
ptr = L.length - 1;
while(ptr >= idx) {
L.elem[ptr+1]= L.elem[ptr];
ptr--;
}
L.elem[idx] = e;
L.length++;
return true;
}
//方法二
bool InsertOrderList(SqList &L, ElemType e) {
//思路:在顺序表从后往前找第一个比e小的元素idx,那么idx+1就是e的存储位置。遍历过程中,如果L.elem[i]>x,则把i处的元素后移一个位置。
int i = L.length-1;
if(L.size>=MaxSize) {//顺序表已满
return false;
} else {
for(; i>=0 && x<L.elem[i]; i--) L.elem[i+1]=L.elem[i];
L.elem[i+1]=x;
L.length++;
return true;
}
}
[2019年第2题].
方法一
void Delete(LinkList &L) {
LNode *fast = L;
LNode *slow = NULL;
while (fast != NULL) {
bool isOp = false;//处理fast != NULL时,进行了删除操作。
if (fast->next != NULL && fast->data == fast->next->data) {//说明此时发现存在重复元素
slow = fast;
fast = fast->next;
while (fast != NULL && fast->data == slow->data) {
fast = fast->next;
}
//此时fast要么为空,要么fast的前一个元素与slow指向结点的data相同
if (fast == NULL) {
slow->next = NULL;
return;
} else if (fast != NULL) {
isOp = true;
slow->next = fast; //这里有点问题fast->data=2
slow = NULL;
}
}
if (!isOp) fast = fast->next;
}
}
方法二、遍历单链表,如果ptr->val = ptr->next->val,则ptr->next = ptr->next->next;
void Delete(LinkList &L) {
if (!head) return;
LNode* cur = L->next;
while (cur->next) {
if (cur->val == cur->next->val) {
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
}
[2019年第4题].
(1)、利用双指针,初始情况下,front指针指向第一个记录,end指针指向最后一个记录。移动front指针,如果front对应记录的关键字为非负数,则向前移动end指针,直到找到关键字为负数的记录,交换front与end对应记录的关键字key。继续上述过程,直到front>=end。
(2)、
void Process(SqList L) {
int front=1, end = L.length;
while(front < end) {
if(L.r[front].key >= 0) {
//如果front与end之间存在记录的关键字为负,则找到该记录
while(front < end && L.r[end].key >= 0) {
end--;
}
if(front < end) { //交换front和end指向的记录的关键字
int tmp = L.r[end].key;
L.r[end].key= L.r[front].key;
L.r[front].key = tmp;
front++;
end--;
}
}
else front++;
}
}
[2020年第1题].
void DeleteMin_Sq(LinkList &L) {
//遍历一遍顺序表找到最小元素的下标idx,然后再将idx后面的元素全部往前移动一个位置
if(L.length == 0) return;
int ptr=0, idx = 0;
while(ptr < L.length) { //找到最小元素的下标
if(L.elem[ptr] < L.elem[idx])
idx = ptr;
ptr++;
}
for(int i = idx; i < L.length-1;i++) { //将idx后面的元素全部往前移动一个位置。
L.elem[i] = L.elem[i+1];
}
L.length--;
}
[2020年第3题].
bool InsertOrderList(LinkList &L, ElemType e) {
//总体思路:找到第一个比e大的元素的前一个元素target,然后将e插入target后即可。若单链表中的元素都比e小,则插入单链表的末尾。
LNode *newNode = (LNode *)malloc(sizeof(LNode));
if(newNode == NULL) return false;
newNode->data = e;
LNode *slow = L, *fast = L->next;
while(fast) {
if(fast->data <= e) {
fast = fast->next;
slow = slow ->next;
} else break;//此时slow指向的结点就是要找的target
}
slow->next = newNode;
newNode->next = fast;
return true;
}
[2021年第1题]. 见[2019年第2题]解答。
综合分析题
[2023年第1题]. 待优化的地方:这个题我把实际业务场景考虑太多了,考试只要按照题目条件来就行了。
(1)、
对于增加新同学操作,需要保证按照学号递增排列:
顺序存储和链式存储的时间复杂度都是O(1)。
对于删除新同学操作:
顺序存储:二分查找(学号,电话)或 遍历(姓名)+ 移动后面元素。时间复杂度:
链式存储:遍历查找+删除操作。时间复杂度:O(N)
对于改操作:
顺序存储:查找+改。
链式存储:查找+改。遍历查找时间复杂度:O(N),改操作时间复杂度:O(1)。
综上:顺序存储和链式存储各有优劣,总体表现差不多,因此,选择链式存储。
(2)、
typedef struct Record {
int Number;
char *Name;
int Telephone;
Record *next;
} Record;
typedef struct ConList {//通讯录
Record *head; //不存储实际数据的头节点
int nums; //通讯录中的学生总数
}ConList;
(3)、
void Delete(char *name, ConList &list, int nameLen) {
//思路:使用快慢指针处理
bool isDel = false;
Record *slow = list.head;
Record *ptr = list.head->next;
while(ptr) {
bool istarget = true;
for(int i = 0; i<=nameLen - 1;i++) {
if(ptr->name[i] != name[i]) { //说明该同学姓名不为name
istarget = false;
break;
}
}
if(istarget) {//找到目标同学,删除完成之后并没有直接退出,因为可能存在重名的同学
isDel = true;
slow ->next = ptr ->next;
}
slow = slow ->next;
ptr = ptr->next;
}
if(!isDel) {
printf("该同学不在本班");
}
}
(4)、
void insert (int number, char *name, int telephone, ConList &list) {
//思路:使用快慢指针
Record *slow = list.head;
Record *fast = slow->next;
Record *newNode = (Record *) malloc(sizeof(Record));
newNode->number = number;
newNode->name = name;
newNode->telephone = telephone;
newNode->next = NULL;
while(fast) {
if(fast->number == number) {
slow->next = newNode;
newNode->next = fast->next;
return;
} else if(fast->number > number) {//找到第一个比number大的同学,那么slow->next就是新同学将要插入的位置
slow->next = newNode;
newNode->next = fast;
return;
}
slow = slow -> next;
fast = fast ->next;
}
//说明新同学的学号已有同学的学号都大,插入末尾
slow->next = newNode;
}