数据结构基础(2)

数据结构基础(2)

线性表的定义:

线性表是具有相同数据类型的n(n>= 0)个数据元素的有限序列,其中n为表长,当n = 0时线性表是一个空表。

注意:

  1. 每个数据元素所占空间是一样大的
  2. 是有次序的
  3. 线性表中的位序是从1开始的,数组下标是从0开始的

线性表的基本操作:

  1. 初始化表:构造一个空的线性表,分配内存空间
  2. 销毁操作:销毁线性表,并释放线性表L所占用的内存空间
  3. 插入操作:在表L中的第i个位置上插入指定元素e
  4. 删除操作:删除表L中第i个位置的元素,并用e返回删除元素的值(需引用符号)
  5. 按值查找操作:在表L中查找具有给定关键字的元素
  6. 按位查找操作:获取表L中第i个位置的元素的值
  7. ​ 其他常用操作:
    1. 求表长:返回线性表L的长度,即L中数据元素的个数
    2. 输出操作:按前后顺序输出线性表L的所有元素值
    3. 判空操作:若L位空表,则返回true,否则返回false

tips:

  1. 创销增删改查
  2. 什么时候要传入引用"&"--对参数的修改结果需要"带回来"

顺序表的定义:

顺序表--用顺序存储的方式实现线性表

如何知道一个数据元素的大小?
用sizeof(ElemType)

顺序表的实现--静态分配(大小不可改)

例如:

#define MaxSize 10  //定义最大长度
typedef struct {
	ElemType data[MaxSize];   //用静态的"数组"存放数据元素
	int length;  //顺序表的当前长度
}SqList;  //顺序表的类型定义(静态分配方式)

顺序表的实现--动态分配

#define InitSize 10  //顺序表初始化长度
typedef struct {
	ElemType *data;   //指示动态分配数组的指针
	int MaxSize;     //顺序表的最大容量
	int length;     //顺序表的当前长度
}SeqList;  //顺序表的类型定义(静态分配方式)

key: 动态申请和释放内存空间

c-- malloc,free函数

c++ -- new,delete 关键字

举例:

#include <stdlib.h>

#define InitSize 10  // 默认的最大长度
typedef struct {
    int *data;       // 指示动态分配数组的指针
    int MaxSize;     // 顺序表的最大容量
    int length;      // 顺序表的当前长度
} SeqList;

// 初始化顺序表
void InitList(SeqList &L) {
    // 用 malloc 函数申请一片连续的存储空间
    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;  // 顺序表最大长度增加 len
    free(p);  // 释放原来的内存空间
}

int main() {
    SeqList L;      // 声明一个顺序表
    InitList(L);    // 初始化顺序表
    //...往顺序表中随便插入几个元素...
    IncreaseSize(L, 5);
    return 0;
}

顺序表的特点:

  1. 随机访问,即可以在O(1)时间内找到第i个元素
  2. 存储密度高,每个节点只存储数据元素
  3. 拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)
  4. 插入、删除操作不方便,需要移动大量元素

顺序表的基本操作--插入

ListInsert(&L,i,e) : 插入操作:在表L中的第i个位置上插入指定元素e

#define MaxSize 10  // 定义最大长度
typedef struct {
    int data[MaxSize];  // 用静态的“数组”存放数据元素
    int length;         // 顺序表的当前长度
} SqList;              // 顺序表的类型定义

bool ListInsert(SqList &L, int i, int e) {
  
    // 插入位置 i 应该满足 1 <= i <= L.length + 1,这样才能保证插入到合理位置
    if (i < 1 || i > L.length + 1) {
        // 位置不合法,无法插入,返回 false
        return false;
    }
    // 如果当前顺序表的长度已经达到了最大容量 MaxSize,就不能再插入新元素了
    if (L.length >= MaxSize) {
        return false;
    }
    for (int j = L.length; j >= i; j--) {
        L.data[j] = L.data[j - 1];
    }
    
    L.data[i - 1] = e;  // 将新元素 e 放到腾出的位置(也就是数组下标为 i - 1 的地方 )
    L.length++;
    return true;
}

int main() {
    SqList L;         // 声明一个顺序表
    InitList(L);      // 初始化顺序表(需补充 InitList 函数定义才能正常运行)
    //...此处省略一些代码,插入几个元素
    ListInsert(L, 3, 3);
    return 0;
}

注意位序,数组下标的关系,并从后面的元素依次移动

分析时间复杂度:

最好情况:新元素插入到表尾,不需要移动元素 O(1)

最坏情况:新元素插入到表头,需要将原有的n个元素全都向后移动,O(n)

平均情况:O(n)

顺序表的基本操作--删除

ListDelete(&L,&e) : 删除操作:删除表L中第i个位置的元素,并用e返回删除元素的值

#define MaxSize 100  // 假设最大长度,可根据实际调整
typedef struct {
    int data[MaxSize];
    int length;
} SqList;

// 函数声明(如果在实际代码中,若函数定义在调用之后,可能需要声明,这里按逻辑提取)
bool ListDelete(SqList &L, int i, int &e);
void InitList(SqList &L);  // 该函数需补充具体实现

bool ListDelete(SqList &L, int i, int &e) {
    if (i < 1 || i > L.length)  // 判断 i 的范围是否有效
        return false;
    e = L.data[i - 1];  // 将被删除的元素赋值给 e
    for (int j = i; j < L.length; j++)  // 将第 i 个位置后的元素前移
        L.data[j - 1] = L.data[j];
    L.length--;  // 线性表长度减 1
    return true;
}

int main() {
    SqList L;        // 声明一个顺序表
    InitList(L);     // 初始化顺序表(需补充 InitList 函数实现)
    //...此处省略一些代码,插入几个元素
    int e = -1;      // 用变量 e 把删除的元素“带回来”
    if (ListDelete(L, 3, e))
        printf("已删除第 3 个元素,删除元素值为=%d\n", e);
    else
        printf("位序 i 不合法,删除失败\n");
    return 0;
}

注意位序,数组下标的关系,并从前面的元素依次移动

分析时间复杂度:

最好情况:删除表尾元素,不需要移动元素 O(1)

最坏情况:删除表头,需要将原有的n-1个元素全都向前移动,O(n)

平均情况:O(n)

顺序表的按位查找--静态分配

GetElem(L,i) : 按位查找操作,获取表 L 中第 i 个位置的元素的值

#define MaxSize 10  // 定义最大长度
typedef struct {
    ElemType data[MaxSize];  // 用静态的“数组”存放数据元素
    int length;              // 顺序表的当前长度
} SqList;                    // 顺序表的类型定义(静态分配方式)

ElemType GetElem(SqList L, int i) {
    return L.data[i - 1];
}

顺序表的按位查找--动态分配

GetElem(L,i) : 按位查找操作,获取表 L 中第 i 个位置的元素的值

#define InitSize 10  
typedef struct {  
    ElemType *data;  
    int MaxSize;  
    int length;  
} SeqList;  

ElemType GetElem(SeqList L, int i) {  
    return L.data[i - 1];  
} 

时间复杂度:O(1)

顺序表的按值查找--动态分配

typedef struct {
    int *data;   // 指示动态分配数组的指针
    int MaxSize;   // 顺序表的最大容量
    int length;  // 顺序表的当前长度
} SeqList;

// 在顺序表 L 中查找第一个元素值等于 e 的元素,并返回其位序
int LocateElem(SeqList L, int e) {
    for (int i = 0; i < L.length; i++)
        if (L.data[i] == e)
            return i + 1;
    return 0;
}

注意:在C语言中,结构体的比较不能直接用"== "来比较

时间复杂度:

最好情况:目标元素在表头 O(1)

最坏情况:目标元素在表尾O(n)

平均情况:O(n)

posted @ 2025-08-28 22:57  YA10JUN  阅读(14)  评论(0)    收藏  举报