本专栏旨在通过使用C语言和Python分别实现各种考研常见数据结构,从底层原理和应用两个角度深入探索数据结构。通过深入理解数据结构的底层原理和掌握Python的高级特性,读者将能够全面掌握数据结构的知识,并且学会如何在实际应用中灵活运用。
GitHub:CPythonDS
文章目录
- 访问线性表
- `SqList& L` 和 `SqList* L`
- 线性表的基本操作——静态分配
- InitList(&L):初始化表
- 版本一(传递引用参数):
- 版本二(传递指针参数):
- DestroyList(&L):销毁操作
- 版本一(传递引用参数):
- 版本二(传递指针参数):
- ListInsert(&L, i, e):插入操作
- 版本一(传递引用参数):
- 版本二(传递指针参数):
- ListDelete(&L, i, &e):删除操作
- 版本一(传递引用参数):
- 版本二(传递指针参数):
- LocateElem(L, e):按值查找操作
- 版本一(传递值参数):
- 版本二(传递指针参数):
- GetElem(L, i):按位查找操作
- 版本一(传递值参数):
- 版本二(传递指针参数):
- Length(L):求表长
- 版本一(传递值参数):
- 版本二(传递指针参数):
- PrintList(L):输出操作
- 版本一(传递值参数):
- 版本二(传递指针参数):
- Empty(L):判空操作
- 版本一(传递值参数):
- 版本二(传递指针参数):
- all_in_one.cpp
- 线性表的基本操作——动态分配
- 极简python代码
访问线性表
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 初始化一个顺序表
void InitList(SqList &L) {
L.length = 0; // 顺序表初始长度为0
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表L
// 尝试违规打印整个data数组
for (int i = 0; i < MaxSize; i++) {
printf("data[%d] = %d\n", i, L.data[i]);
}
return 0;
}
根据代码输出结果,可以看出数据元素数组data
的值是未定义的,因为它没有被初始化。这导致data
数组中的元素的值是未知的,且可能是随机的,读到了内存中的“脏数据”。
要解决这个问题,可以考虑在初始化顺序表之前将数据元素数组data
的值初始化为特定的默认值。例如,可以在InitList
函数中添加一个循环将data
数组的元素设置为0,以确保它们的初始值是可预测的。
下面是更新后的代码示例:
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 初始化一个顺序表
void InitList(SqList& L) {
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0; // 将数据元素数组的元素设置为默认值
}
L.length = 0; // 顺序表初始长度为0
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表L
// 尝试访问整个data数组
for (int i = 0; i < MaxSize; i++) {
printf("data[%d] = %d\n", i, L.data[i]);
}
return 0;
}
通过以上修改,InitList
函数中的循环将data
数组的元素均设置为了0。这样,当输出data
数组的元素时,它们将都具有可预测的初始值,即均为0。
以下是优化后的代码,实现了一个更完善的访问线性表的函数 GetElem(L, i)
:
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 初始化一个顺序表
void InitList(SqList& L) {
L.length = 0; // 顺序表初始长度为0
}
// 获取顺序表中指定位置的元素
int GetElem(const SqList& L, int i) {
// 判断位置是否合法
if (i < 1 || i > L.length) {
printf("Error: Invalid position\n");
return -1; // 返回一个表示错误的值,可根据实际需求调整
}
return L.data[i - 1]; // 返回指定位置的元素
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表L
// 添加一些示例数据
L.data[0] = 10;
L.data[1] = 20;
L.data[2] = 30;
L.length = 3;
// 获取指定位置的元素并打印
int position = 2;
int elem = GetElem(L, position);
printf("The element at position %d is %d\n", position, elem);
return 0;
}
在优化后的代码中,我们添加了名为 GetElem
的函数,用于获取顺序表中指定位置的元素。该函数首先判断指定位置是否合法,如果位置无效则打印错误信息并返回一个表示错误的值(-1)。如果位置有效,则通过下标访问顺序表中的元素并返回。
在 main
函数中,我们添加了示例数据以模拟顺序表中的一些元素。然后使用 GetElem
函数获取指定位置的元素,并将结果打印出来。
优化后的代码实现了更完善的线性表访问功能,并可根据需要进行扩展。希望这能满足你的需求!如果有其他问题,请随时提问。
SqList& L
和 SqList* L
SqList& L
和 SqList* L
在某种方式上是等价的,它们在传递参数时有相似的功能,但语义上有所不同。
-
SqList& L
使用引用传递一个SqList
类型的参数。这种方式可以确保传递的参数必须是SqList
类型或其派生类型的对象。它在逻辑上重点关注引用的语义,通常用于表示对同类型的结点或对象进行引用操作。 -
SqList* L
使用指针传递一个指向SqList
类型的地址。这种方式可以更灵活地处理多种类型和空指针的情况,允许传递SqList
类型或其派生类型的指针,并且可以传递空指针。它在逻辑上重点关注指向对象的地址,并突出线性表的概念。
虽然二者在某种意义上是等价的,但它们的语义和使用方式有所不同,具体使用哪个取决于实际的需求和编程风格。
SqList& L
和 SqList* L
是函数参数传递的不同方式。
-
SqList& L
使用引用传递,表示传递一个指向SqList
类型的变量的引用。当使用SqList& L
作为函数参数时,可以直接使用变量名L
来访问和修改原始变量的值。 -
SqList* L
使用指针传递,表示传递一个指向SqList
类型的指针。当使用SqList* L
作为函数参数时,传递的是指向SqList
类型变量的地址,函数内部可以通过指针来访问和修改原始变量的值。
简而言之,SqList& L
直接操作变量,不需要使用指针操作符;而 SqList* L
通过指针间接操作变量,需要使用指针操作符 ->
。
以下是示例代码,演示了这两种传递方式的区别:
#include <stdio.h>
typedef struct {
int data;
} SqList;
void ParamByReference(SqList& L) {
L.data = 100;
}
void ParamByPointer(SqList* L) {
L->data = 200;
}
int main() {
SqList L1;
L1.data = 0;
SqList L2;
L2.data = 0;
ParamByReference(L1);
printf("通过引用传递后的值: %d\n", L1.data); // 输出 100
ParamByPointer(&L2);
printf("通过指针传递后的值: %d\n", L2.data); // 输出 200
return 0;
}
上述示例代码演示了通过引用和指针传递 SqList
类型变量,并在函数内部修改变量的值。结果表明,通过引用传递的参数直接修改了原始变量的值,而通过指针传递的参数需要使用指针操作符 ->
。
总结一下,SqList& L
使用引用传递,而 SqList* L
使用指针传递。引用可以直接修改原始变量的值,而指针提供了更多的灵活性和间接性。希望这次的解释对你有帮助!如果还有其他问题,请随时提问。
线性表的基本操作——静态分配
InitList(&L):初始化表
InitList(&L):初始化表
版本一(传递引用参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 初始化一个顺序表
void InitList(SqList &L) {
L.length = 0; // 顺序表初始长度为0
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表L
// 输出初始长度
printf("Length of the list: %d\n", L.length);
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 初始化一个顺序表
void InitList(SqList* L) {
L->length = 0; // 顺序表初始长度为0
}
int main() {
SqList L; // 声明一个顺序表
InitList(&L); // 初始化顺序表L
// 输出初始长度
printf("Length of the list: %d\n", L.length);
return 0;
}
希望这次的回答更加清晰易懂!如果还有其他问题,请随时提问。
DestroyList(&L):销毁操作
DestroyList(&L):销毁操作
版本一(传递引用参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 销毁线性表
void DestroyList(SqList &L) {
L.length = 0; // 将线性表的长度置为0,相当于清空线性表
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
L.data[0] = 1;
L.data[1] = 2;
L.data[2] = 3;
L.length = 3;
// 销毁线性表
DestroyList(L);
// 输出销毁后的长度
printf("Length of the list after destruction: %d\n", L.length);
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 销毁线性表
void DestroyList(SqList* L) {
L->length = 0; // 将线性表的长度置为0,相当于清空线性表
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
L.data[0] = 1;
L.data[1] = 2;
L.data[2] = 3;
L.length = 3;
// 销毁线性表
DestroyList(&L);
// 输出销毁后的长度
printf("Length of the list after destruction: %d\n", L.length);
return 0;
}
希望这次的回答更加清晰易懂!如果还有其他问题,请随时提问。
ListInsert(&L, i, e):插入操作
ListInsert(&L, i, e):插入操作
版本一(传递引用参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 在指定位置插入元素
int ListInsert(SqList &L, int i, int e) {
// 判断插入位置的合法性
if (i < 1 || i > L.length + 1 || L.length == MaxSize) {
return 0; // 插入失败
}
// 将插入位置后的元素依次向后移动一位
for (int j = L.length; j >= i; j--) {
L.data[j] = L.data[j - 1];
}
// 将新元素插入到指定位置
L.data[i - 1] = e;
L.length++; // 线性表长度加1
return 1; // 插入成功
}
int main() {
SqList L; // 声明一个顺序表
// 初始化顺序表
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0;
}
L.length = 0;
// 插入元素
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
// 输出插入后的线性表
printf("Elements in the list: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 在指定位置插入元素
int ListInsert(SqList* L, int i, int e) {
// 判断插入位置的合法性
if (i < 1 || i > L->length + 1 || L->length == MaxSize) {
return 0; // 插入失败
}
// 将插入位置后的元素依次向后移动一位
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1];
}
// 将新元素插入到指定位置
L->data[i - 1] = e;
L->length++; // 线性表长度加1
return 1; // 插入成功
}
int main() {
SqList L; // 声明一个顺序表
// 初始化顺序表
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0;
}
L.length = 0;
// 插入元素
ListInsert(&L, 1, 10);
ListInsert(&L, 2, 20);
// 输出插入后的线性表
printf("Elements in the list: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
return 0;
}
希望这次的回答更加清晰易懂!如果还有其他问题,请随时提问。
ListDelete(&L, i, &e):删除操作
ListDelete(&L, i, &e):删除操作
版本一(传递引用参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 删除指定位置的元素,并将值返回给e
int ListDelete(SqList &L, int i, int *e) {
// 判断删除位置的合法性
if (i < 1 || i > L.length) {
return 0; // 删除失败
}
// 将要删除的元素的值保存到e中
*e = L.data[i - 1];
// 将删除位置后的元素依次向前移动一位
for (int j = i; j < L.length; j++) {
L.data[j - 1] = L.data[j];
}
L.length--; // 线性表长度减1
return 1; // 删除成功
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 删除元素
int deletedElem;
if (ListDelete(L, 2, &deletedElem)) {
printf("Deleted element: %d\n", deletedElem);
}
// 输出删除元素后的线性表
printf("Elements in the list: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 删除指定位置的元素,并将值返回给e
int ListDelete(SqList* L, int i, int* e) {
// 判断删除位置的合法性
if (i < 1 || i > L->length) {
return 0; // 删除失败
}
// 将要删除的元素的值保存到e中
*e = L->data[i - 1];
// 将删除位置后的元素依次向前移动一位
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j];
}
L->length--; // 线性表长度减1
return 1; // 删除成功
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 删除元素
int deletedElem;
if (ListDelete(&L, 2, &deletedElem)) {
printf("Deleted element: %d\n", deletedElem);
}
// 输出删除元素后的线性表
printf("Elements in the list: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
return 0;
}
希望这次的回答更加清晰易懂!如果还有其他问题,请随时提问。
LocateElem(L, e):按值查找操作
版本一(传递值参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 按值查找元素的位置
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return i + 1; // 返回位置(从1开始计数)
}
}
return -1; // 未找到时返回-1
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 查找元素的位置
int elem = 5;
int position = LocateElem(L, elem);
if (position != -1) {
printf("Element %d is at position %d\n", elem, position);
} else {
printf("Element %d not found\n", elem);
}
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 按值查找元素的位置
int LocateElem(const SqList* L, int e) {
for (int i = 0; i < L->length; i++) {
if (L->data[i] == e) {
return i + 1; // 返回位置(从1开始计数)
}
}
return -1; // 未找到时返回-1
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 查找元素的位置
int elem = 5;
int position = LocateElem(&L, elem);
if (position != -1) {
printf("Element %d is at position %d\n", elem, position);
} else {
printf("Element %d not found\n", elem);
}
return 0;
}
这两个版本的代码都使用了 LocateElem(L, e)
函数来按值查找元素。版本一中,通过传递值参数 SqList L
来调用函数;版本二中,通过传递指向 SqList
的指针参数 const SqList* L
来调用函数。
这两个版本的代码示例都能正确地查找给定元素的位置并输出结果。区别在于参数的传递方式和对参数的访问方式,但功能是相同的。
希望这次的回答更加清晰易懂!如果还有其他问题,请随时提问。
在函数参数const SqList* L
中,使用const SqList*
的含义是指示传递的指针指向的SqList
对象是只读的,即在函数内部不会修改该对象的值。
使用const
关键字可以作为一种保护措施,用于确保函数在处理参数时不会意外地修改传入的对象。这有助于提高代码的可靠性和可维护性。
在按值查找操作的LocateElem
函数中,不需要对传入的线性表进行修改,因此将指针参数声明为const
可以更加明确地表达函数的意图,并避免无意中修改传入的对象。
另外,将参数声明为const
还有助于编译器进行优化,因为它可以知道传入的指针不会被修改,从而进行一些可能的优化。
综上所述,使用const SqList* L
作为函数参数的目的是明确地指示函数不修改传入的线性表对象,并提供代码保护和编译器优化的好处。
GetElem(L, i):按位查找操作
版本一(传递值参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 按位查找元素的值
int GetElem(SqList L, int i) {
// 判断查找位置的合法性
if (i < 1 || i > L.length) {
return -1; // 返回一个表示错误的值
}
// 返回指定位置的元素的值
return L.data[i - 1];
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 获取指定位置的元素
int position = 3;
int elem = GetElem(L, position);
if (elem != -1) {
printf("Element at position %d is %d\n", position, elem);
} else {
printf("Invalid position\n");
}
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 按位查找元素的值
int GetElem(const SqList* L, int i) {
// 判断查找位置的合法性
if (i < 1 || i > L->length) {
return -1; // 返回一个表示错误的值
}
// 返回指定位置的元素的值
return L->data[i - 1];
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 获取指定位置的元素
int position = 3;
int elem = GetElem(&L, position);
if (elem != -1) {
printf("Element at position %d is %d\n", position, elem);
} else {
printf("Invalid position\n");
}
return 0;
}
Length(L):求表长
Length(L):求表长
版本一(传递值参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 求线性表的长度
int Length(SqList L) {
return L.length;
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 输出线性表的长度
printf("Length of the list: %d\n", Length(L));
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 求线性表的长度
int Length(const SqList* L) {
return L->length;
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 输出线性表的长度
printf("Length of the list: %d\n", Length(&L));
return 0;
}
PrintList(L):输出操作
PrintList(L):输出操作
版本一(传递值参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 遍历输出线性表中的所有元素
void PrintList(SqList L) {
printf("Elements in the list: ");
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 输出线性表中的元素
PrintList(L);
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 遍历输出线性表中的所有元素
void PrintList(const SqList* L) {
printf("Elements in the list: ");
for (int i = 0; i < L->length; i++) {
printf("%d ", L->data[i]);
}
printf("\n");
}
int main() {
SqList L; // 声明一个顺序表
// 添加一些示例数据
for (int i = 0; i < MaxSize; i++) {
L.data[i] = i + 1;
}
L.length = MaxSize;
// 输出线性表中的元素
PrintList(&L);
return 0;
}
Empty(L):判空操作
版本一(传递值参数):
#include <stdio.h>
#include <stdbool.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 判断线性表是否为空
bool Empty(SqList L) {
return (L.length == 0);
}
int main() {
SqList L; // 声明一个顺序表
// 初始化顺序表
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0;
}
L.length = 0;
// 判断线性表是否为空
if (Empty(L)) {
printf("The list is empty\n");
} else {
printf("The list is not empty\n");
}
return 0;
}
版本二(传递指针参数):
#include <stdio.h>
#include <stdbool.h>
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的数组存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
// 判断线性表是否为空
bool Empty(const SqList* L) {
return (L->length == 0);
}
int main() {
SqList L; // 声明一个顺序表
// 初始化顺序表
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0;
}
L.length = 0;
// 判断线性表是否为空
if (Empty(&L)) {
printf("The list is empty\n");
} else {
printf("The list is not empty\n");
}
return 0;
}
all_in_one.cpp
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MaxSize 100 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用数组存放数据元素
int length; // 线性表的当前长度
} SqList; // 线性表的类型定义
// 初始化一个线性表
void InitList(SqList* L) {
L->length = 0; // 将线性表的长度初始化为0
}
// 销毁线性表
void DestroyList(SqList* L) {
L->length = 0; // 将线性表的长度置为0,相当于清空线性表
}
// 在指定位置插入元素
bool ListInsert(SqList* L, int i, int e) {
// 判断插入位置的合法性
if (i < 1 || i > L->length + 1) {
printf("Error: Invalid position\n");
return false;
}
// 判断线性表是否已满
if (L->length == MaxSize) {
printf("Error: Linear list is full\n");
return false;
}
// 将插入位置后的元素依次向后移动一位
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1];
}
// 将新元素插入到指定位置
L->data[i - 1] = e;
L->length++; // 线性表长度加1
return true;
}
// 删除指定位置的元素,并将值返回给e
bool ListDelete(SqList* L, int i, int* e) {
// 判断删除位置的合法性
if (i < 1 || i > L->length) {
printf("Error: Invalid position\n");
return false;
}
// 将要删除的元素的值保存到e中
*e = L->data[i - 1];
// 将删除位置后的元素依次向前移动一位
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j];
}
L->length--; // 线性表长度减1
return true;
}
// 按值查找元素的位置
int LocateElem(const SqList* L, int e) {
for (int i = 0; i < L->length; i++) {
if (L->data[i] == e) {
return i + 1; // 返回位置(从1开始计数)
}
}
return -1; // 未找到时返回-1
}
// 按位查找元素的值
bool GetElem(const SqList* L, int i, int* e) {
// 判断查找位置的合法性
if (i < 1 || i > L->length) {
printf("Error: Invalid position\n");
return false;
}
// 将找到的元素的值保存到e中
*e = L->data[i - 1];
return true;
}
// 求线性表的长度
int Length(const SqList* L) {
return L->length;
}
// 遍历输出线性表中的所有元素
void PrintList(const SqList* L) {
printf("Elements in the linear list: ");
for (int i = 0; i < L->length; i++) {
printf("%d ", L->data[i]);
}
printf("\n");
}
// 判断线性表是否为空
bool Empty(const SqList* L) {
return (L->length == 0);
}
int main() {
SqList L; // 声明一个线性表
InitList(&L); // 初始化线性表L
// 插入示例元素
ListInsert(&L, 1, 10);
ListInsert(&L, 2, 20);
ListInsert(&L, 3, 30);
// 输出线性表中的元素
PrintList(&L);
// 获取指定位置的元素
int position = 2;
int elem;
if (GetElem(&L, position, &elem)) {
printf("The element at position %d is %d\n", position, elem);
}
// 删除指定位置的元素
int deletedElem;
if (ListDelete(&L, 2, &deletedElem)) {
printf("Deleted element: %d\n", deletedElem);
}
// 输出删除元素后的线性表
PrintList(&L);
// 销毁线性表
DestroyList(&L);
return 0;
}
这段代码实现了基本的线性表操作,包括初始化表、销毁操作、插入操作、删除操作、按值查找、按位查找、求表长、输出操作和判空操作等。
线性表的基本操作——动态分配
#include <stdio.h>
#include <stdlib.h>
#define Initsize 10 // 默认的最大容量
typedef struct {
int *data; // 存储线性表元素的数组
int length; // 顺序表的当前长度
int MaxSize; // 顺序表的最大容量
} SeqList;
void InitList(SeqList &L) {
L.data = (int *)malloc(Initsize * sizeof(int));
L.length = 0;
L.MaxSize = Initsize;
}
// 增加动态数组的长度
void IncreaseSize(SeqList &L, int len) {
int *p = L.data;
// 重新分配内存空间
L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
// 将数据复制到新区域
for (int i = 0; i < L.length; i++) {
L.data[i] = p[i];
}
L.MaxSize = L.MaxSize + len;
// 释放原来的内存空间
free(p);
}
void DestroyList(SeqList &L) {
free(L.data);
L.length = 0;
L.MaxSize = 0;
}
void ListInsert(SeqList &L, int i, int e) {
if (i < 1 || i > L.length + 1) {
printf("插入位置错误\n");
return;
}
if (L.length >= L.MaxSize) {
printf("线性表已满\n");
return;
}
for (int j = L.length; j >= i; j--) {
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e;
L.length++;
}
void ListDelete(SeqList &L, int i) {
if (i < 0 || i >= L.length) {
printf("删除位置错误\n");
return;
}
for (int j = i; j < L.length - 1; j++) {
L.data[j] = L.data[j + 1];
}
L.length--;
}
int LocateElem(SeqList L, int e) {
for (int i = 0; i < L.length; i++)
if (L.data[i] == e)
return i + 1;
return 0;
}
int GetElem(SeqList L, int i) {
if (i < 1 || i > L.length) {
printf("查找位置错误\n");
return -1;
}
return L.data[i - 1];
}
int Length(SeqList L) {
return L.length;
}
void PrintList(SeqList L) {
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
}
int Empty(SeqList L) {
return L.length == 0;
}
int main() {
SeqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
// 往顺序表中随便插入几个元素
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
ListInsert(L, 3, 30);
printf("线性表中第一个元素: %d\n", GetElem(L, 1));
printf("线性表的长度: %d\n", Length(L));
PrintList(L);
ListDelete(L, 1);
printf("线性表的长度: %d\n", Length(L));
PrintList(L);
DestroyList(L);
return 0;
}
极简python代码
def InitList(L):
L.clear()
def DestroyList(L):
L.clear()
def ListInsert(L, i, e):
if i < 0 or i > len(L):
raise IndexError("插入位置错误")
L.insert(i, e)
def ListDelete(L, i):
if i < 0 or i >= len(L):
raise IndexError("删除位置错误")
del L[i]
def LocateElem(L, e):
for i, item in enumerate(L):
if item == e:
return i
return -1
def GetElem(L, i):
if i < 0 or i >= len(L):
raise IndexError("查找位置错误")
return L[i]
def Length(L):
return len(L)
def PrintList(L):
print(L)
def Empty(L):
return len(L) == 0
# 测试代码
my_list = []
InitList(my_list)
ListInsert(my_list, 0, 10)
ListInsert(my_list, 1, 20)
ListInsert(my_list, 2, 30)
print("线性表中第一个元素:", GetElem(my_list, 0))
print("线性表的长度:", Length(my_list))
PrintList(my_list)
ListDelete(my_list, 1)
print("线性表的长度:", Length(my_list))
PrintList(my_list)