广东财经大学考研初试数据结构历年真题分类参考答案:线性表

48 阅读5分钟

选择题

[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(log2N)+O(N)O(N)O(log_2{N})+O(N)或O(N)

​ 链式存储:遍历查找+删除操作。时间复杂度:O(N)

对于改操作:

​ 顺序存储:查找+改。

根据关键字查找,有两种方式,二分查找(学号,电话)或遍历(姓名),时间复杂度分别为O(log2N)O(N)改操作时间复杂度:O(1)根据关键字查找,有两种方式,二分查找(学号,电话)或 遍历(姓名),\\ 时间复杂度分别为O(log_2{N}),O(N)。\\ 改操作时间复杂度:O(1)。

​ 链式存储:查找+改。遍历查找时间复杂度: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;
}