图源:文心一言
考研笔记整理~🥝🥝
之前的博文链接在此:数据结构02:线性表[顺序表+链表]_线性链表-CSDN博客~🥝🥝
本篇作为线性表的代码补充,供小伙伴们参考~🥝🥝
- 第1版:王道书的课后习题~🧩🧩
编辑:梅头脑🌸
参考用书:王道考研《2025年 数据结构考研复习指导》
目录
🧵01 删除顺序表最小值
🧩题目
🌰解题
🧵02 逆置顺序表
🧩题目
🌰解题
🧵03 删除指定元素01
🧩题目
🌰解法
🧵04 删除指定元素02
🧩题目
🌰解题
🧵05-1 有序表删除重复元素
🧩题目
🌰解法
🧵05-2 无序表删除重复元素
🧩题目
🌰解法
🧵06 两个有序表合成一个有序表
🧩题目
🌰解法
🧵07 顺序表位置互换
🧩题目
🌰解法
🧵08 顺序表查找元素
🧩题目
🌰解法
🧵09 输出3个序列中相同的元素
🧩题目
🌰解法
🔚结语
🧵01 删除顺序表最小值
🧩题目
从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
🌰解题
📇解题思路
- 遍历数组,记录数组的最小值 min 与 下标 index;
- 按照题意,用最末尾的数组替换最小数字;
- 数组长度 L.length - 1;
⌨️解题代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
}SqList;
bool DeleteMin(SqList& L) {
if (L.length == 0) return false;
int min = INT_MAX;
int index = INT_MAX;
int i;
for (i = 0; i < L.length; i++) {
if (L.data[i] <= min) {
min = L.data[i];
index = i;
}
}
L.data[index] = L.data[L.length - 1];
L.length--;
return true;
}
int main() {
SqList L = { { 8, 9, 3, 4, 5, 1, 6, 7, 0, 2 },10 };
bool result = DeleteMin(L);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵02 逆置顺序表
🧩题目
设计一个高效算法,将顺序表工的所有元素逆置,要求算法的空间复杂度为 O(1)。
🌰解题
📇解题思路
- 使用指针 i 遍历数组,交换第 i 位和第 length - 1 - i位,循环length / 2次以后得到结果~
⌨️解题代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
}SqList;
bool Reverse(SqList& L) {
if (L.length == 0) return false;
if (L.length == 1) return true;
int temp = 0;
for (int i = 0; i < L.length / 2; i++) {
temp = L.data[i];
L.data[i] = L.data[L.length - 1 - i];
L.data[L.length - 1 - i] = temp;
}
return true;
}
int main() {
SqList L = { { 8, 9, 3, 4, 5, 1, 6, 7, 0, 2 }, 10 };
Reverse(L);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵03 删除指定元素01
🧩题目
对长度为n的顺序表L,编写一个时间复杂度为 0(n)、空间复杂度为 O(1)的算法,该算法删除顺序表中所有值为x的数据元素。
🌰解法
📇算法思路
- 遍历数组:
- 如果指针 i 遍历到的当前元素 != x,则count + 1,该元素 向前移动 count 位;
- 如果指针 i 遍历到的当前元素 == x,跳过这个元素,开始比较下一个元素;
- 遍历完成以后,末尾count位元素直接移除,原地完成数组复制~
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
}SqList;
bool Delete_X(SqList& L, int x) {
if (L.length == 0) return false;
int count = 0;
for (int i = 0; i < L.length; i++) {
L.data[i - count] = L.data[i];
if (L.data[i] == x) {
count++;
}
}
L.length = L.length - count;
return true;
}
int main() {
SqList L = { { 8, 2, 3, 4, 2, 1, 6, 2, 0, 2 },10 };
int x = 2;
Delete_X(L, x);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵04 删除指定元素02
🧩题目
从顺序表中删除其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t 不合理或顺序表为空,则显示出错信息并退出运行。
🌰解题
📇解题思路
- 遍历数组:
- 如果指针 i 遍历到的当前元素 >t 或 <s,则k + 1,该元素 向前移动 k 位;
- 如果指针 i 遍历到的当前元素 <= t 且 >=s,跳过这个元素,开始比较下一个元素;
- 遍历完成以后,将k的长度赋值给 L.length,原地完成数组复制;
- 备注:
- 没错,与上一道题目的算法思路是完全一致的~
- 以下2种代码都可以运行,没有实质性的差别,相对来说,代码1要略好一些~
⌨️算法代码1
#include <iostream>
#include <climits> // INT_MAX
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool Delete_s_to_t(SqList& L, int s, int t) {
if (L.length == 0 || s > t) return false;
int k = 0; // 用于记录需要保留的元素的位置
for (int i = 0; i < L.length; i++) {
if (L.data[i] < s || L.data[i] > t) { // 如果当前元素不在范围[s, t]内,则保留该元素
L.data[k++] = L.data[i]; // 将该元素移动到前面空出的位置上,并更新k的值
}
}
L.length = k; // 更新顺序表的长度
return true;
}
int main() {
SqList L = { {8, 2, 3, 4, 2, 1, 6, 2, 0, 2}, 10 }; // 使用初始化列表来设置数组的元素和长度,注意这里使用了双大括号来初始化结构体中的数组和长度两个成员变量
int s = 3, t = 6;
Delete_s_to_t(L, s, t);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
⌨️算法代码2
bool Delete_s_to_t(SqList& L, int s, int t) {
if (L.length == 0 || s > t) return false;
int count = 0;
for (int i = 0; i < L.length; i++) {
L.data[i - count] = L.data[i];
if (L.data[i] >= s && L.data[i] <= t) {
count++;
}
}
L.length = L.length - count;
return true;
}
🧵05-1 有序表删除重复元素
🧩题目
从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
🌰解法
📇算法思路
- 遍历数组:
- 如果指针 i 遍历到的当前元素 == 上一个数字,则k + 1,该元素 向前移动 k 位;
- 如果指针 i 遍历到的当前元素 != 上一个数字,跳过这个元素,开始比较下一个元素;
- 遍历完成以后,将k的长度赋值给 L.length,原地完成数组复制;
- 备注:没错,与上一道题目的算法思路是完全一致的~
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool DeleteSame(SqList& L) {
if (L.length == 0) return false;
if (L.length == 1) return true;
int k = 1;
for (int i = 1; i < L.length; i++) {
if (L.data[i] != L.data[i - 1]) {
L.data[k++] = L.data[i];
}
}
L.length = k; // 更新顺序表的长度
return true;
}
int main() {
SqList L = { {0, 0, 1, 1, 1, 2, 2, 3, 3, 4 }, 10 };
DeleteSame(L);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵05-2 无序表删除重复元素
🧩题目
从无序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
🌰解法
📇算法思路1
- 排序;
- 然后遍历数组:
- 如果指针 i 遍历到的当前元素 == 上一个数字,则k + 1,该元素 向前移动 k 位;
- 如果指针 i 遍历到的当前元素 != 上一个数字,跳过这个元素,开始比较下一个元素;
- 遍历完成以后,将k的长度赋值给 L.length,原地完成数组复制;
- 备注:没错,与上一道题目的算法思路是完全一致的~
⌨️算法代码1
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool DeleteSame(SqList& L) {
if (L.length == 0) return false;
if (L.length == 1) return true;
int temp, i, j;
for (i = 1; i < L.length; i++) {
if (L.data[i] < L.data[i - 1]) {
temp = L.data[i];
for (j = i - 1; j >= 0 && temp < L.data[j]; j--) {
L.data[j + 1] = L.data[j];
}
L.data[j + 1] = temp;
i = j + 1;
}
}
int m = 0;
for (int n = 0; n < L.length; n++) {
if (n == 0 || L.data[n] != L.data[n - 1]) {
L.data[m++] = L.data[n];
}
}
L.length = m; // 更新顺序表的长度
return true;
}
int main() {
SqList L = { {1, 1, 0, 0, 1, 2, 3, 4, 2, 3 }, 10 };
DeleteSame(L);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
中间增加了一段简单选择排序算法,就是int i, j, temp之后的for循环(emm...之后有机会详细说这是什么情况,但简单来说,它会从第2个元素开始,与前面的所有元素比较,如果小于则往前移动,直到表中所有元素有序为止)~
如果实在想不起来排序算法怎么办...emm,也可以用这个平替...
sort(L.data, L.data + L.length);
📇算法思路2
- 哈希表,首先遍历数组所有的元素,存入哈希表;哈希表的首列会记录元素,次列会记录该元素的输出次数;
- 然后,输出哈比表的首列元素至L.data中,并更新顺序表的长度~
⌨️算法代码2
// 哈希表法
#include <iostream>
#include <unordered_map>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool DeleteSame(SqList& L) {
if (L.length == 0) return false;
if (L.length == 1) return true;
unordered_map<int, int> nums;
for (int i = 0; i < L.length; i++) {
nums[L.data[i]]++;
}
int j = 0;
for (auto it = nums.begin(); it != nums.end(); ++it) {
L.data[j++] = it->first;
}
L.length = nums.size(); // 更新顺序表的长度
return true;
}
int main() {
SqList L = { {1, 1, 0, 0, 1, 2, 3, 4, 2, 3 }, 10 };
DeleteSame(L);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵06 两个有序表合成一个有序表
🧩题目
将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
🌰解法
📇算法思路
- 遍历数组,使用 i指针 遍历S1,使用 j指针 遍历S2;
- 如果 S1.data[i] <= S2.data[j],将S1.data[i]记入S3.data[k],i 往后移动1位;
- 反之,将S2.data[j]记入S3.data[k],j 往后移动1位;
- 如果指针 i、j 其中之一遍历到末尾,停止循环,把另一个数组的末尾搬到S3的末尾;
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool Merge(SqList& L1, SqList& L2, SqList& L3) {
if (L1.length + L2.length > L3.length) return false;
int i = 0, j = 0, k = 0;
while (i < L1.length && j < L2.length) {
if (L1.data[i] <= L2.data[j]) {
L3.data[k++] = L1.data[i++];
}
else {
L3.data[k++] = L2.data[j++];
}
}
while (i < L1.length) {
L3.data[k++] = L1.data[i++];
}
while (j < L2.length) {
L3.data[k++] = L2.data[j++];
}
L3.length = k;
return true;
}
int main() {
SqList L1 = { {0, 3, 4, 6, 7, 13, 15, 17, 18, 19 }, 10 };
SqList L2 = { {1, 2, 5, 8, 9, 10, 11, 12, 14, 16 }, 10 };
SqList L3 = { {}, 20 };
Merge(L1, L2, L3);
for (int i = 0; i < L3.length; i++) {
cout << L3.data[i] << " ";
}
cout << endl;
return 0;
}
🧵07 顺序表位置互换
🧩题目
已知在一维数组 A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,…,bn)放在(a1,a2,a3,…,am)的前面。
🌰解法
📇算法思路
- 算法思想:
- 将数组p(n-p)转化为数组(n-p)p,(n-p)p=(p-1(n-p)-1)-1;
- 因此分别反转前p项,后n-p项,最后整体反转p-1(n-p)-1;
- reverse函数用于反转数组中指定范围的元素,它通过交换两端的元素来实现反转。
- 时间复杂度:O(n),其中n是数组的长度,因为需要反转数组的两部分和整体数组。
- 空间复杂度:O(1),因为算法只使用了固定的额外空间来存储一些临时变量,与数组的长度无关。
- 备注:题目解法与10年真题是一样的,在下一篇博文中提供了具体的演算流程。
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
void Swap(int& a, int& b) {
int temp;
temp = a;
a = b;
b = temp;
}
bool Exchange(SqList& L, int m, int n) {
if (L.length == 0 or L.length == 1) return true;
if (m + n != L.length) return false;
int i = 0, j = 0, k = 0;
while (i < m / 2) {
Swap(L.data[i], L.data[m - 1 - i]);
i++;
}
while (j < n / 2) {
Swap(L.data[m + j], L.data[m + n - 1 - j]);
j++;
}
while (k < (m + n) / 2) {
Swap(L.data[k], L.data[m + n - 1 - k]);
k++;
}
return true;
}
int main() {
SqList L = { {0, 3, 4, 6, 7, 13, 15, 17, 18, 19 }, 10 };
// int m = 6, n = 4;
int m = 5, n = 5;
Exchange(L, m, n);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵08 顺序表查找元素
🧩题目
线性表(ai, a2, a3,…,an)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法。完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换;若找不到,则将其插入表中并使表中元素仍递增有序,
🌰解法
📇算法思路
- 最少时间就是提示使用折半查找:如果数组中间的元素大于指定元素,则查找数组的前一半,否则,查找数组的后一半;
- if 找到元素,交换两个元素;
- else,定位的当前位置,元素全部后移一个位置(注意是从倒数第一个元素起,每次向后移动一位),空出当前的位置,插入元素~
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
void Swap(int& a, int& b) {
int temp;
temp = a;
a = b;
b = temp;
}
void Insert(SqList& L, int locate, int target) {
for (int i = L.length - 1; i > locate; i--) {
L.data[i] = L.data[i - 1];
}
L.data[locate] = target;
}
bool Locate(SqList& L, int target) {
if (L.length == 0) return true;
int front = 0, back = L.length - 1, mid = (front + back) / 2;
while (L.data[mid] != target && front <= back) {
mid = (front + back) / 2;
if (target < L.data[mid]) {
back = mid - 1;
}
else {
front = mid + 1;
}
}
if (L.data[mid] == target) {
if (mid < L.length - 1) {
Swap(L.data[mid], L.data[mid + 1]);
}
}
else {
if (target < L.data[mid]) {
Insert(L, mid, target);
}
else {
Insert(L, mid + 1, target);
}
}
return true;
}
int main() {
SqList L = { {0, 3, 4, 6, 7, 13, 15, 17, 18, 19 }, 10 };
// int m = 6;
int m = 5;
Locate(L, m);
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
return 0;
}
🧵09 输出3个序列中相同的元素
🧩题目
给定三个序列 A、B、C,长度均为n,且均为无重复元素的递增序列,请设计一个时间09.上尽可能高效的算法,逐行输出同时存在于这三个序列中的所有元素。例如,数组A为{1,2,3},数组B为{2,3,4},数组C为{-1,0,2},则输出 2。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或 C++语言描述算法,关键之处给出注释,3)说明你的算法的时间复杂度和空间复杂度。
🌰解法
📇算法思路
- 算法思想:
- 指针 i, j, k从前向后遍历,每次寻找都会使指针向数组中最大的元素对齐,直至3个数字完全相同为止;
- 这道题目的解题思路与20年的真题非常地像,在本系列下一篇博文会写到~
- 时间复杂度:O(L1 + L2 + L3);
- 空间复杂度:O(1)。
⌨️算法代码
#include <iostream>
using namespace std;
#define Maxsize 20
typedef struct {
int data[Maxsize];
int length;
} SqList;
bool FindCommon(SqList& L1, SqList& L2, SqList& L3) {
if (L1.length == 0 || L2.length == 0 || L3.length == 0) return false;
int i = 0, j = 0, k = 0;
int maxnum = max(L1.data[i], max(L2.data[j], L3.data[k]));
while (i < L1.length && j < L2.length && k < L3.length) {
if (L1.data[i] != maxnum || L2.data[j] != maxnum || L3.data[k] != maxnum) {
if (L1.data[i] < maxnum) { i++; }
if (L2.data[j] < maxnum) { j++; }
if (L3.data[k] < maxnum) { k++; }
maxnum = max(L1.data[i], max(L2.data[j], L3.data[k]));
}
else {
cout << "i = " << i << ",j = " << j << ",k = " << k << ",num = " << maxnum << endl;
i++; j++; k++;
}
}
return true;
}
int main() {
SqList L1 = { {1, 2, 3}, 3 };
SqList L2 = { {2, 3, 4}, 3 };
SqList L3 = { {-1, 0, 2}, 3 };
FindCommon(L1, L2, L3);
return 0;
}
🔚结语
博文到此结束,写得模糊或者有误之处,欢迎小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~😶🌫️
我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,收到点赞的话,博主肝文的动力++~🌟🌟
同系列的博文:🌸数据结构_梅头脑_的博客-CSDN博客
同博主的博文:🌸随笔03 笔记整理-CSDN博客