【408直通车】C+Python赋能数据结构:从底层原理到高级应用的蜕变之路——线性表

Source

本专栏旨在通过使用C语言和Python分别实现各种考研常见数据结构,从底层原理和应用两个角度深入探索数据结构。通过深入理解数据结构的底层原理和掌握Python的高级特性,读者将能够全面掌握数据结构的知识,并且学会如何在实际应用中灵活运用。

GitHub:CPythonDS

访问线性表

#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& LSqList* L

SqList& LSqList* L 在某种方式上是等价的,它们在传递参数时有相似的功能,但语义上有所不同。

  • SqList& L 使用引用传递一个 SqList 类型的参数。这种方式可以确保传递的参数必须是 SqList 类型或其派生类型的对象。它在逻辑上重点关注引用的语义,通常用于表示对同类型的结点或对象进行引用操作。

  • SqList* L 使用指针传递一个指向 SqList 类型的地址。这种方式可以更灵活地处理多种类型和空指针的情况,允许传递 SqList 类型或其派生类型的指针,并且可以传递空指针。它在逻辑上重点关注指向对象的地址,并突出线性表的概念。

虽然二者在某种意义上是等价的,但它们的语义和使用方式有所不同,具体使用哪个取决于实际的需求和编程风格。

SqList& LSqList* 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)