数据结构—顺序表

线性表

定义:具有相同数据类型的n个数据元素的有限序列

顺序表

注意这里的定义:顺序表是线性表的顺序存储

特点:

  • 可以随机存储
  • 存储密度较高,无额外的指针开销,适合频繁访问元素,较少插入、删除操作的场景

顺序表的存储结构

假定线性表的数据元素类型为ElemType,静态分配方式:

c 复制代码
#define MaxSize 50
typedef struct{
	ElemType data[MaxSize];
	int length; // 顺序表当前长度
}SqList;

动态分配:

c 复制代码
#define MaxSize 50
typedef struct{
	ElemType *data; // 动态分配内存的基地址
	int length; // 实际长度(当前顺序表中已存储的数据元素个数)
	int MaxSize; // 数组的最大容量
}SqList;

// C初始动态分配语句
L.data = (ElemType *)malloc(sizeof(ElemType) * InitSize)

动态内存分配和静态内存分配

静态分配 动态分配
在程序编译时就已经确定了内存大小和位置,不占用CPU资源 在程序运行时根据需要动态地分配和释放内存,需要占用CPU资源
用于:全局变量、静态变量、常量 C:malloc, free
其内存由编译器自动管理 由程序员手动管理,包括分配和释放。
内存大小和生命周期都是固定的 内存大小和生命周期可以在运行时动态改变
通常在栈段或.data段中分配 通常在堆(heap)中分配,函数调用时传递的是指针

引用符&和地址无关

c 复制代码
SqList list;          // 原变量 list
SqList &L = list;     // L 是 list 的引用(别名)

你操作 L.data,就等同于操作 list.data,完全不需要关心 "地址"------ 编译器会自动关联到原变量,不需要你手动处理地址

顺序表的初始化

静态:

c 复制代码
SqList L;
void InitSqList(SqList &L)
{
	L.length = 0;
}

动态:

c 复制代码
void InitSqList(SqList &L)
{
	L.data = (Elemtype *)malloc(sizeof(Elemtype) * InitSize)
	L.length = 0; // 初始长度=0
	L.MaxSize = InitSize; // 初始存储容量
}

顺序表的插入

c 复制代码
int InsertSqList(SqList &L, int i, int e)
{
	// 检查i的值是否合法
	if (i < 1 || i > L.length + 1)
		return false;
	// 检查顺序表是否已满
	if (L.length == MaxSize)
	{
		return false;
	}
	// L.data[j]已经是当前最后一个值的后一位了
	for(j = L.length; j >= i; j--)
		{
			L.data[j] = L.data[j-1];
		}
	L.data[i-1] = e;
	// 顺序表当前长度加1
	L.length++;
	return e;
}

顺序表的删除

c 复制代码
bool DeleteSqList(SqList& L, int i, int* e)
// 如果使用 int e 作为参数,函数内部对 e 的修改只会在函数内部生效(属于局部变量),无法将删除的元素值传递到函数外部
{
	// 检查i的值是否合法
	if (i < 1 || i > L.length)
		return false;

	*e = L.data[i - 1]; // 使用指针接收删除的元素
	for (int j = i; j < L.length; j++)
	{
		L.data[j - 1] = L.data[j];
	}
	L.length--;
	return true;
}

顺序表的查找

  • 按值查找
c 复制代码
// 时间复杂度为O(n)
int GetItem(SqList &L, int e)
{
	for(int j = 0; j < L.length; j++)
	{
		if (L.data[j] == e)
			return j + 1;
	}
	return 0;
}
  • 按序号查找
c 复制代码
int GetItem(SqList& L, int i, int e)
{
	// 检查i的值是否合法
	if (i < 1 || i > L.length)
		return false;
	e = L.data[i - 1];
	return e;
}

完整代码

c 复制代码
// 这里的代码是用C实现的,因为C并不支持引用的方式,这里把引用都改为指针
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ElemType int
#define MaxSize 50

typedef struct {
    ElemType data[MaxSize];
    int length; // 顺序表当前长度
} SqList;

// 初始化顺序表
void InitSqList(SqList* L) {
    L->length = 0;
}

// 在顺序表第i个位置插入元素e(i从1开始)
bool InsertSqList(SqList* L, int i, int e) {
    // 检查i的值是否合法
    if (i < 1 || i > L->length + 1)
        return false;
    // 检查顺序表是否已满
    if (L->length == MaxSize)
        return false;
    
    int j;
    for (j = L->length; j >= i; j--) {
        L->data[j] = L->data[j - 1];
    }
    L->data[i - 1] = e;
    L->length++;
    return true;
}

// 删除顺序表第i个位置的元素,并通过指针e返回该元素
bool DeleteSqList(SqList* L, int i, int* e) {
    // 检查i的值是否合法
    if (i < 1 || i > L->length)
        return false;
    
    *e = L->data[i - 1]; // 保存要删除的元素
    // 移动元素覆盖被删除的位置
    for (int j = i; j < L->length; j++) {
        L->data[j - 1] = L->data[j];
    }
    L->length--;
    return true;
}

// 按值查找,返回元素e在顺序表中的位置(1开始),未找到返回0
int LocateElem(SqList* L, int e) {
    for (int j = 0; j < L->length; j++) {
        if (L->data[j] == e)
            return j + 1; // 返回位序(从1开始)
    }
    return 0; // 未找到
}

// 按位置查找,返回顺序表第i个位置的元素
ElemType GetElemByIndex(SqList* L, int i) {
    // 检查i的值是否合法
    if (i < 1 || i > L->length) {
        printf("位置不合法\n");
        return -1; // 假设-1不是合法数据
    }
    return L->data[i - 1];
}

// 打印顺序表所有元素
void PrintSqList(SqList* L) {
    printf("顺序表内容: ");
    for (int i = 0; i < L->length; i++) {
        printf("%d ", L->data[i]);
    }
    printf("(长度: %d)\n", L->length);
}

int main() {
    SqList L;
    InitSqList(&L); 
    
    // 测试插入操作
    InsertSqList(&L, 1, 10);
    InsertSqList(&L, 2, 20);
    InsertSqList(&L, 3, 30);
    InsertSqList(&L, 2, 15); // 在位置2插入15
    PrintSqList(&L);
    
    // 测试查找操作
    int pos = LocateElem(&L, 20);
    if (pos != 0)
        printf("元素20的位置是: %d\n", pos);
    else
        printf("未找到元素20\n");
    
    ElemType val = GetElemByIndex(&L, 3);
    printf("位置3的元素是: %d\n", val);
    
    // 测试删除操作
    int delVal;
    if (DeleteSqList(&L, 2, &delVal))
        printf("删除的元素是: %d\n", delVal);
    PrintSqList(&L);
    
    return 0;
}

//顺序表内容: 10 15 20 30 (长度: 4)
//元素20的位置是: 3
//位置3的元素是: 20
//删除的元素是: 15
//顺序表内容: 10 20 30 (长度: 3)
相关推荐
失散132 小时前
软件设计师——03 数据结构(下)
数据结构·软考·图论·软件设计师
努力还债的学术吗喽2 小时前
pycharm找不到Tencent Cloud CodeBuddy如何安装[windows]?pycharm插件市场找不到插件如何安装?
ide·windows·pycharm·插件·plugin·codebuddy
两千次2 小时前
写csv测试
服务器·数据库·windows
yiqiqukanhaiba3 小时前
Linux编程笔记2-控制&数组&指针&函数&动态内存&构造类型&Makefile
数据结构·算法·排序算法
安当加密3 小时前
SLA操作系统双因素认证实现Windows远程桌面OTP双因子安全登录—从零搭建企业级RDP安全加固体系
windows·安全
nice_lcj5204 小时前
Java 集合框架之 List 全面解析(从概念到实践)
java·windows·list
高山上有一只小老虎5 小时前
输出单向链表中倒数第k个结点
java·数据结构·链表
Algo-hx5 小时前
数据结构入门 (五):约束即是力量 —— 深入理解栈
数据结构·算法
我要用代码向我喜欢的女孩表白5 小时前
数据结构13003考前急救
数据结构
NiKo_W6 小时前
C++ 反向迭代器模拟实现
开发语言·数据结构·c++·stl