1. 定义顺序表结构 SeqList
data: 存储数据的数组。index: 数组元素的索引 (下标),从 0 开始。length: 顺序表中当前元素的数量。
#define MAX_SIZE 8
struct SeqList
{
int data[MAX_SIZE]; //数据空间
int length; //当前长度
};
2. 初始化顺序表 initSeqList(SeqList &L, int arr[], int n)
初始化调用函数:
int Main()
{
int arr[] = {1,2,3,4,5};
int n = sizeof(arr)/sizeof(arr[0]);
SeqList L;
initSeqList(L, arr, n);
}
void initSeqList(SeqList &L)
{
L.length = 0;
}
L.length = 0,长度初始化如下:
void initSeqList(SeqList &L, int arr[], int n)
{
for (int i = 0; i < n; i++)
{
L.data[i] = arr[i];
}
L.length = n;
}
初始化过程(循环)
初始化后:
3. 打印顺序表 (printSeqList(SeqList &L))
假设 L.data = {1, 2, 3,4,5}, L.length = 5):
void printSeqList(SeqList &L)
{
for (int i = 0; i < L.length; ++i)
{
printf("%d ", L.data[i]);
}
printf("\n");
}
4. 尾部插入数据 insertSeqListTail(SeqList &L, int x)
void insertSeqListTail(SeqList &L, int x)
{
//判断顺序表是否已满
if (L.length >= MAX_SIZE)
{
printf("顺序表已满,无法插入数据\n");
return;
}
//将数据插入到顺序表尾部
L.data[L.length] = x; // 将新元素x存入顺序表当前末尾位置
// data数组的索引正好等于当前长度值(因为数组从0开始)
// 例如当length=3时,元素存储在索引0,1,2,新元素应放在索引3的位置
L.length++;
}
- 功能: 在顺序表的末尾插入元素
x。 - 图示 (假设
L.data = {1, 2, 3},L.length = 3,x = 4):
插入前:
插入过程:
插入后:
5. 头部插入数据 insertSeqListHead(SeqList &L, int x)
void insertSeqListHead(SeqList &L, int x)
{
//判断顺序表是否已满
if (L.length >= MAX_SIZE)
{
printf("顺序表已满,无法插入数据\n");
return;
}
//将数据插入到顺序表头部
//将顺序表中所有元素后移一位
//第一种方法:
for (int i = L.length; i > 0; --i)
{
L.data[i] = L.data[i-1]; //将i-1位置的元素移到i位置
}
//将新元素x存入顺序表头部
L.data[0] = x;
L.length++;
//第二种方法:
// for (int i = L.length-1; i >= 0; --i)
// {
// L.data[i+1] = L.data[i]; //将i位置的元素移到i+1位置
// }
// L.data[0] = x;
// L.length++;
}
- 功能: 在顺序表的头部插入元素 x。
- 图示 (假设
L.data = {1, 2, 3},L.length = 3,x = 0):
插入前:
SeqList L:
+--------+-------------------------------------+
| data | [1] [2] [3] [ ] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 3 |
+--------+-------------------------------------+
插入过程(元素后移):
for (i = L.length; i > 0; i--)
L.data[i] = L.data[i - 1];
i = 3: L.data[3] <--- L.data[2] (3)
[1] [2] [3] [ ] ...
^
|
[3]
i = 2: L.data[2] <--- L.data[1] (2)
[1] [2] [3] [3] ...
^
|
[2]
i = 1: L.data[1] <--- L.data[0] (1)
[1] [2] [2] [3] ...
^
|
[1]
x (0) ---> L.data[0]
[ ] [1] [2] [3] ...
^
|
0
L.length++; (L.length 变为 4)
插入后:
SeqList L:
+--------+-------------------------------------+
| data | [0] [1] [2] [3] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
6. 在指定位置插入数据 insertSeqListPos(SeqList &L, int pos, int x)
void insertSeqListPos(SeqList &L, int pos, int x)
{
//判断顺序表是否已满
if (L.length >= MAX_SIZE)
{
printf("顺序表已满,无法插入数据\n");
return;
}
//判断插入位置是否合法
if (pos < 0 || pos > L.length)
{
printf("插入位置不合法\n");
return;
}
//将数据插入到指定位置
//将顺序表中所有元素后移一位
for (int i = L.length; i > pos; --i)
{
L.data[i] = L.data[i-1]; //将i-1位置的元素移到i位置
}
//将新元素x存入指定位置
L.data[pos] = x;
L.length++;
}
- 功能: 在索引
pos处插入元素x。 - 图示 (假设
L.data = {1, 2, 3},L.length = 3,pos = 1,x = 5):
插入前:
SeqList L:
+--------+-------------------------------------+
| data | [1] [2] [3] [ ] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 3 |
+--------+-------------------------------------+
插入过程(元素后移):
插入后:
SeqList L:
+--------+-------------------------------------+
| data | [1] [5] [2] [3] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
7.删除数据 deleteElem(SeqList &L, int key)
void deleteElem(SeqList &L, int key)
{
//判断顺序表是否为空
if (L.length == 0)
{
printf("顺序表为空,无法删除数据\n");
return;
}
//先要查找key在顺序表中的位置
int pos = 0;
while (pos < L.length && L.data[pos] != key)
{
pos++;
}
if (pos >= L.length) //判断key是否存在
{
printf("删除的key不存在\n");
return;
}
//删除数据
//将顺序表中所有元素前移一位
for (int i = pos; i < L.length-1; ++i)
{
L.data[i] = L.data[i+1]; //将i+1位置的元素移到i位置
}
//更新长度
L.length--;
}
- 功能: 删除第一个值为
key的元素。 - 图示 (假设
L.data = {1, 5, 2, 3},L.length = 4,key = 5):
删除前:
SeqList L:
+--------+-------------------------------------+
| data | [1] [5] [2] [3] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
删除过程(查找和元素前移):
删除后:
SeqList L:
+--------+-------------------------------------+
| data | [1] [2] [3] [3] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 3 |
+--------+-------------------------------------+
8.反转顺序表 reverseSeqList(SeqList &L)
void reverseSeqList(SeqList &L)
{
//判断顺序表是否为空
if (L.length == 0)
{
printf("顺序表为空,无法反转\n");
return;
}
//反转顺序表
int left = 0;
int right = L.length-1;
while (left < right)
{
//交换左右两个元素
int temp = L.data[left];
L.data[left] = L.data[right];
L.data[right] = temp;
//更新左右指针(更新区间)
left++;
right--;
}
}
- 功能: 将顺序表中的元素倒序排列。
- 图示 (假设
L.data = {1, 2, 3, 4},L.length = 4):
反转前:
SeqList L:
+--------+-------------------------------------+
| data | [1] [2] [3] [4] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
left = 0
right = 3
反转过程(循环交换):
while (left < right) {
temp = L.data[left];
L.data[left] = L.data[right];
L.data[right] = temp;
left++;
right--;
}
1. left = 0, right = 3:
交换 L.data[0] 和 L.data[3]:
[1] [2] [3] [4] ---> [4] [2] [3] [1]
^ ^ ^ ^
2. left = 1, right = 2:
交换 L.data[1] 和 L.data[2]:
[4] [2] [3] [1] ---> [4] [3] [2] [1]
^ ^ ^ ^
3. left = 2, right = 1: 循环条件 (left < right) 不满足,结束。
反转后:
SeqList L:
+--------+-------------------------------------+
| data | [4] [3] [2] [1] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
9. 排序顺序表 sortSeqList(SeqList &L) - 使用冒泡排序
void sortSeqList(SeqList &L)
{
int n = L.length;
//冒泡排序
for (int i = 0; i < n-1; ++i)
{
for (int j = 0; j < n-i-1; ++j)
{
if (L.data[j] > L.data[j+1])
{
int temp = L.data[j];
L.data[j] = L.data[j+1];
L.data[j+1] = temp;
}
}
}
}
- 功能: 将顺序表中的元素按升序排列。
- 图示 (假设
L.data = {4, 2, 1, 3},L.length = 4- 仅展示第一轮):
排序前:
SeqList L:
+--------+-------------------------------------+
| data | [4] [2] [1] [3] [ ] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 4 |
+--------+-------------------------------------+
排序过程(第一轮冒泡排序):
for (i = 0; i < n - 1; i++) { // 外层循环 (n = L.length)
for (j = 0; j < n - i - 1; j++) { // 内层循环
if (L.data[j] > L.data[j + 1]) {
// 交换 L.data[j] 和 L.data[j + 1]
}
}
}
i = 0:
j = 0: 比较 L.data[0] (4) 和 L.data[1] (2) -> 4 > 2, 交换
[4] [2] [1] [3] ---> [2] [4] [1] [3]
index 0 1 2 3 0 1 2 3
^ ^ ^ ^
j = 1: 比较 L.data[1] (4) 和 L.data[2] (1) -> 4 > 1, 交换
[2] [4] [1] [3] ---> [2] [1] [4] [3]
index 0 1 2 3 0 1 2 3
^ ^ ^ ^
j = 2: 比较 L.data[2] (4) 和 L.data[3] (3) -> 4 > 3, 交换
[2] [1] [4] [3] ---> [2] [1] [3] [4]
index 0 1 2 3 0 1 2 3
^ ^ ^ ^
-
第一轮结束后:
L.data = {2, 1, 3, 4}(最大的元素 4 已移至最后)后续轮次类似,直到整个顺序表有序。
10. 二分查找 binarySearch(SeqList &L, int key) - 元素有顺序是前提
int binarySearch(SeqList &L, int key)
{
int left = 0;
int right = L.length-1;
while (left <= right)
{
int mid = (left + right) / 2;
if (L.data[mid] == key)
{
return mid;
}
else if (L.data[mid] < key)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
- 功能: 在已排序的顺序表中查找值为 key 的元素。
- 图示 (假设
L.data = {1, 2, 3, 4, 5},L.length = 5,key = 3):
SeqList L (已排序):
+--------+-------------------------------------+
| data | [1] [2] [3] [4] [5] [ ] [ ] [ ] |
| index | 0 1 2 3 4 5 6 7 |
+--------+-------------------------------------+
| length | 5 |
+--------+-------------------------------------+
left = 0
right = 4
查找过程:
while (left <= right) {
mid = (left + right) / 2;
if (L.data[mid] == key) {
return mid; // 找到,返回索引
} else if (L.data[mid] < key) {
left = mid + 1; // 在右半部分查找
} else {
right = mid - 1; // 在左半部分查找
}
}
return -1; // 未找到
1. mid = (0 + 4) / 2 = 2
L.data[2] (3) == key (3) -> 返回 2 (找到)
如果 key = 6 (未找到):
mid= 2,L.data[2] (3)< 6,left= 3mid= 3,L.data[3] (4)< 6,left= 4mid= 4,L.data[4] (5)< 6,left= 5left(5) >right(4), 循环结束, 返回 -1
11. 合并有序顺序表 mergeSeqList(SeqList &L1, SeqList &L2, SeqList &L)
void mergeSeqList(SeqList &L1, SeqList &L2, SeqList &L)
{
int i = 0; //L1的索引
int j = 0; //L2的索引
int k = 0; //L的索引
while (i < L1.length && j < L2.length)
{
if (L1.data[i] <= L2.data[j])
L.data[k++] = L1.data[i++]; //将L1的元素存入L
else
L.data[k++] = L2.data[j++]; //将L2的元素存入L
}
while (i < L1.length)
L.data[k++] = L1.data[i++]; //合并剩余的L1元素 因为有时会两组数据长度不一样,有一组数据合并完了,另一组数据还没有合并完,所以要将剩余的元素合并到L中
while (j < L2.length)
L.data[k++] = L2.data[j++]; //合并剩余的L2元素
L.length = k; //更新L的长度
}
- 功能: 将两个已排序的顺序表 L1 和 L2 合并到 L。
- 图示 (假设
L1.data = {1, 3, 5},L1.length = 3,L2.data)
合并前:
i = 0 (L1 的索引)
j = 0 (L2 的索引)
k = 0 (L 的索引)
1. L1[0] (1) <= L2[0] (2) -> L[0] = 1, i++, k++
2. L1[1] (3) > L2[0] (2) -> L[1] = 2, j++, k++
3. L1[1] (3) <= L2[1] (4) -> L[2] = 3, i++, k++
4. L1[2] (5) > L2[1] (4) -> L[3] = 4, j++, k++
5. L1[2] (5) <= L2[2] (6) -> L[4] = 5, i++, k++
6. i == L1.length, 循环1结束
剩余L2[2] (6) -> L[5] ,j++ ,k++
j == L2.length, 循环2结束, 循环3结束
合并后:
L: [1] [2] [3] [4] [5] [6] [ ] [ ]
0 1 2 3 4 5 6 7
L.length = 6