数据结构(C语言版)线性表-顺序表

74 阅读11分钟

线性表

定义与特点

由n(n>=0)个数据特性相同的元素构成的有限序列,称为线性表。

线性表是n个数据元素的有限序列,其中n个数据是相同数据类型的。

线性表中元素个数n(n>=0)定义为线性表的长度,当n=0时称之为空表。

对于非空的线性表或线性结构,其特点是:

  • 存在唯一的一个被称作“第一个”的元素;
  • 存在唯一的一个被称作“最后一个”的元素;
  • 第一个元素外,结构中的每个元素均只有一个前驱;
  • 最后一个元素外,结构中的每个元素均只有一个后继。

案例引入:图书信息管理系统

ISBN书名定价
9787302257616计算机基础32
9787302256513程序设计基础46
9787302202816数据库技术与应用39
  1. 查找:根据指定的ISBN或书名查找相应图书的有关信息,并返回该图书在文件中的位置序号。
  2. 插入:插入一条新的图书信息。
  3. 删除:删除一条图书信息。
  4. 修改:根据指定的ISBN,修改该图书的价格。
  5. 排序:将图书按照价格由低到高进行排序。
  6. 计数:统计文件中的图书数量。

顺序表

线性表的 顺序表示 是指用 连续的物理存储空间 存储元素,即「顺序表」—— 元素的逻辑顺序与物理存储顺序完全一致,底层依赖数组实现。

存储结构

#define MAX_SIZE 100     //顺序表可能达到的最大长度
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;               // 当前元素个数(有效长度)
} SeqList;  //顺序表的结构类型为SeqList

屏幕截图 2025-12-03 222357.png

顺序表初始化

void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素
}

完整代码演示:

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;

void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem)); 
	return 0;

}

运行结果:

初始化成功,目前长度占用0

目前占用内存400字节

在尾部添加元素

int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

遍历

void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

添加元素+遍历的完整代码:

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;


void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素

}

int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem));
    
	appendElem(&list, 88);
	appendElem(&list, 56);
	appendElem(&list, 34);
	appendElem(&list, 62);
	appendElem(&list, 45);
	listElemp(&list);
	return 0;
}

运行结果:

初始化成功,目前长度占用0

目前占用内存400字节

88 56 34 62 45

插入元素

屏幕截图 2025-12-04 220041.png

// 在pos位置插入元素e (pos范围:0 ~ L->length)
int insertElem(SeqList* L, int pos, ElemType e)
{
	if (pos <= L->length)
	{
        // 从后往前移动元素(避免覆盖)
		for (int i = L->length - 1; i >= pos - 1; i--)//数组下标:pos - 1
		{
			L->elem[i + 1] = L->elem[i];
		}
        // 插入新元素
		L->elem[pos - 1] = e;
		L->length++;
	}
    return 1;
}

插入元素的完整代码:

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;

//初始化
void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素

}

//添加数据
int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

//遍历
void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

int insertElem(SeqList* L, int pos, ElemType e)
{
	if (L->length >= MAX_SIZE)
	{
		printf("表已经满了\n");
		return 0;
	}
	if (pos<1 || pos > L->length)
	{
		printf("插入位置错误\n");
		return 0;
	}

	if (pos <= L->length)
	{
		for (int i = L->length - 1; i >= pos - 1; i--)
		{
			L->elem[i + 1] = L->elem[i];
		}
		L->elem[pos - 1] = e;
		L->length++;
	}
	return 1;
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem));
    
    //添加元素
	appendElem(&list, 88);
	appendElem(&list, 56);
	appendElem(&list, 34);
	appendElem(&list, 62);
	appendElem(&list, 45);
	printf("原序列:");
	listElemp(&list);
    
    //插入
    insertElem(&list, 2, 24);
	printf("插入新元素后:");
	listElemp(&list);
    
	return 0;
}

运行结果:

屏幕截图 2025-12-04 222002.png

顺序表插入数据的最好时间复杂度是?O(1) ——— 插入到最后的位置

顺序表插入数据的最坏时间复杂度是?O(n) ——— 插入到第一个位置

删除元素

屏幕截图 2025-12-04 223313.png

int delectElem(SeqList* L, int pos, ElemType *e)
{
	//保存删除的元素
	*e = L->elem[pos - 1];
	if (pos < L->length)
	{
		for (int i = pos; i < L->length; i++)
		{
			L->elem[i - 1] = L->elem[i];
		}
	}
	L->length--;
	return 1;
}
#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;

//初始化
void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素

}

//添加数据
int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}
//遍历
void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

//删除数据
int delectElem(SeqList* L, int pos, ElemType *e)
{
	if (L == NULL || pos < 0 || pos >= L->length)
	{
		printf("删除失败:顺序表为空或参数非法\n");
		return 0;
	}
	//保存删除的元素
	*e = L->elem[pos - 1];
	if (pos < L->length)
	{
		for (int i = pos; i < L->length; i++)
		{
			L->elem[i - 1] = L->elem[i];
		}
	}
	L->length--;
	return 1;
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem));
    
    //添加元素
	appendElem(&list, 88);
	appendElem(&list, 56);
	appendElem(&list, 34);
	appendElem(&list, 62);
	appendElem(&list, 45);
	printf("原序列:");
	listElemp(&list);
    
    //删除
	ElemType delect;
	delectElem(&list, 3, &delect);
	printf("删除元素后:");
	listElemp(&list);

	return 0;
}

运行结果:

屏幕截图 2025-12-04 224944.png

查找

int findElem(SeqList* L, ElemType e)
{
	for (int i = 0; i < L->length; i++)
	{
		if (L->elem[i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}

完整代码:

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;


void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素

}

int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

int findElem(SeqList* L, ElemType e)
{
	if (L->length == 0)
	{
		printf("空列表\n");
		return 0;
	}
	for (int i = 0; i < L->length; i++)
	{
		if (L->elem[i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem));
    
    //添加元素
	appendElem(&list, 88);
	appendElem(&list, 56);
	appendElem(&list, 34);
	appendElem(&list, 62);
	appendElem(&list, 45);
	printf("原序列:");
	listElemp(&list);
    
    //查找
	printf("元素62在表中位置:%d\n", findElem(&list, 62));

	return 0;
}

运行结果:

屏幕截图 2025-12-04 230242.png

初始化、添加、插入、删除、查找、遍历全部完整代码

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;  

typedef struct {
	ElemType elem[MAX_SIZE];  // 存储元素的数组
	int length;                 // 当前元素个数(有效长度)
} SeqList;


void InitSeqList(SeqList* L) {
    if (L == NULL) return;
    L->length = 0;  // 初始无元素

}

int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

void listElemp(SeqList* L) 
{
	for (int i = 0; i < L->length; i++) 
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

int insertElem(SeqList* L, int pos, ElemType e)
{
	if (L->length >= MAX_SIZE)
	{
		printf("表已经满了\n");
		return 0;
	}
	if (pos<1 || pos > L->length)
	{
		printf("插入位置错误\n");
		return 0;
	}

	if (pos <= L->length)
	{
		for (int i = L->length - 1; i >= pos - 1; i--)
		{
			L->elem[i + 1] = L->elem[i];
		}
		L->elem[pos - 1] = e;
		L->length++;
	}
	return 1;
}

int delectElem(SeqList* L, int pos, ElemType *e)
{
	if (L->length == 0)
	{
		printf("空表\n");
		return 0;
	}
	if (pos < 0 || pos >= L->length)
	{
		printf("删除失败:删除位置有误\n");
		return 0;
	}
	//保存删除的元素
	*e = L->elem[pos - 1];
	if (pos < L->length)
	{
		for (int i = pos; i < L->length; i++)
		{
			L->elem[i - 1] = L->elem[i];
		}
	}
	L->length--;
	return 1;
}

int findElem(SeqList* L, ElemType e)
{
	if (L->length == 0)
	{
		printf("空列表\n");
		return 0;
	}
	for (int i = 0; i < L->length; i++)
	{
		if (L->elem[i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}

int main()
{
	//声明一个顺序表并初始化
	SeqList list;
	InitSeqList(&list);
	printf("初始化成功,目前长度占用%d\n", list.length);
	printf("目前占用内存%zu字节\n", sizeof(list.elem));

	appendElem(&list, 88);
	appendElem(&list, 56);
	appendElem(&list, 34);
	appendElem(&list, 62);
	appendElem(&list, 45);
	printf("原序列:");
	listElemp(&list);

	insertElem(&list, 2, 24);
	printf("插入新元素后:");
	listElemp(&list);

	ElemType delect;
	delectElem(&list, 3, &delect);
	printf("被删除的数据为:%d\n", delect);
	printf("删除元素后:");
	listElemp(&list);

	printf("元素62在表中位置:%d\n", findElem(&list, 62));

	return 0;
}

动态分配内存地址初始化

// 顺序表结构体:动态数组+当前长度
typedef struct {
	ElemType* elem;// 指向存储元素的动态数组
	int length;    // 当前有效元素个数(而非容量)
}SeqList;

SeqList * initList()
{
	//为顺序表结构体分配内存
	SeqList* L = (SeqList*)malloc(sizeof(SeqList));
	//为存储元素的数组分配内存
	L->elem = (ElemType*)malloc(sizeof(ElemType) * MAX_SIZE);
	//初始化有效长度为0
	L->length = 0;

	return L;
}

添加、插入、删除、遍历元素代码与上面相同

完整代码:

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 100
typedef int ElemType;

// 顺序表结构体:动态数组+当前长度
typedef struct {
	ElemType* elem;// 指向存储元素的动态数组
	int length;    // 当前有效元素个数(而非容量)
}SeqList;

SeqList * initList()
{
	//为顺序表结构体分配内存
	SeqList* L = (SeqList*)malloc(sizeof(SeqList));
	//为存储元素的数组分配内存
	L->elem = (ElemType*)malloc(sizeof(ElemType) * MAX_SIZE);
	//初始化有效长度为0
	L->length = 0;

	return L;
}

int appendElem(SeqList* L, ElemType e)
{
	if (L->length >= MAX_SIZE) {
		printf("顺序表已满\n");
		return 0;
	}
	L->elem[L->length] = e;
	L->length++;
	return 1;
}

void listElemp(SeqList* L)
{
	for (int i = 0; i < L->length; i++)
	{
		printf("%d ", L->elem[i]);
	}
	printf("\n");
}

int insertElem(SeqList* L, int pos, ElemType e)
{
	if (L->length >= MAX_SIZE)
	{
		printf("表已经满了\n");
		return 0;
	}
	if (pos<1 || pos > L->length)
	{
		printf("插入位置错误\n");
		return 0;
	}

	if (pos <= L->length)
	{
		for (int i = L->length - 1; i >= pos - 1; i--)
		{
			L->elem[i + 1] = L->elem[i];
		}
		L->elem[pos - 1] = e;
		L->length++;
	}
	return 1;
}

int delectElem(SeqList* L, int pos, ElemType* e)
{
	if (L->length == 0)
	{
		printf("空表\n");
		return 0;
	}
	if (pos < 0 || pos >= L->length)
	{
		printf("删除失败:删除位置有误\n");
		return 0;
	}
	//保存删除的元素
	*e = L->elem[pos - 1];
	if (pos < L->length)
	{
		for (int i = pos; i < L->length; i++)
		{
			L->elem[i - 1] = L->elem[i];
		}
	}
	L->length--;
	return 1;
}

int findElem(SeqList* L, ElemType e)
{
	if (L->length == 0)
	{
		printf("空列表\n");
		return 0;
	}
	for (int i = 0; i < L->length; i++)
	{
		if (L->elem[i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}

int main()
{
	//声明一个顺序表并初始化
	SeqList* list = initList();
	
	appendElem(list, 88);//直接创建指针,直接代入list
	appendElem(list, 56);
	appendElem(list, 34);
	appendElem(list, 62);
	appendElem(list, 45);
	printf("原序列:");
	listElemp(list);

	printf("插入数据24在第二个位置\n");
	insertElem(list, 2, 24);
	printf("插入新元素后:");
	listElemp(list);

	ElemType delect;
	delectElem(list, 3, &delect);
	printf("被删除的数据为:%d\n", delect);
	printf("删除元素后:");
	listElemp(list);

	printf("元素62在表中位置:%d\n", findElem(list, 62));
	return 0;
}

运行结果:

屏幕截图 2025-12-04 233644.png

线性表的顺序存储形式(顺序表)有哪些点让你觉得麻烦?

插入数据、删除数据得移动位置,怎么解决?链表

链表

单链表的拓展及应用