数据结构—顺序表

线性表

定义:具有相同数据类型的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)
相关推荐
湖南馒头2 小时前
【Win11 启动项BCD文件修复教程】
windows·系统恢复·win1
Jared_devin3 小时前
二叉树算法题—— [蓝桥杯 2019 省 AB] 完全二叉树的权值
数据结构·c++·算法·职场和发展·蓝桥杯
AI 嗯啦4 小时前
数据结构深度解析:二叉树的基本原理
数据结构·算法
hai_qin4 小时前
十三,数据结构-树
数据结构·c++
和光同尘@5 小时前
66. 加一 (编程基础0到1)(Leetcode)
数据结构·人工智能·算法·leetcode·职场和发展
我爱996!6 小时前
LinkedList与链表
数据结构·链表
yb0os16 小时前
RPC实战和核心原理学习(一)----基础
java·开发语言·网络·数据结构·学习·计算机·rpc
帅得不敢出门7 小时前
macOS苹果电脑运行向日葵远程控制软件闪退
windows·macos·远程控制·向日葵
hope_wisdom7 小时前
C/C++数据结构之栈基础
c语言·数据结构·c++··stack