本专栏旨在通过使用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); // 输出 100ParamByPointer(&L2);printf("通过指针传递后的值: %d\n", L2.data); // 输出 200return 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++; // 线性表长度加1return 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++; // 线性表长度加1return 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--; // 线性表长度减1return 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--; // 线性表长度减1return 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++; // 线性表长度加1return 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--; // 线性表长度减1return 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 ireturn -1def 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)