【数据结构考研笔记】线性表 顺序表

唯一可以确定的是,明天会使我们大吃一惊

数据结构 考研复习版

前言:还是要复习这个了,按理说最拿手,拿来引起一下自己的兴趣吧…

数据结构在学什么?

  • 如何用程序代码把现实世界的问题信息化
  • 如何用计算机高效地处理这些信息从而创造价值

第二章 线性表

数据结构三要素——逻辑结构、数据的运算、存储结构(物理结构)

什么是线性表(Linear list)?——逻辑结构

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

每个数据元素所占空间一样大

L = (a1, a2 … an),其中ai是线性表中第i个元素在线性表中的位序

  • 注意:线性表位序从1开始,数组下标从0开始。

a1:表头元素

an:表尾元素

除第一个元素外,每个元素有且只有一个直接前驱;除最后一个元素外,每个元素有且只有一个直接后继

线性表的基本操作——数据的运算

  • void init(&L) 初始化表L,并分配内存
  • void DestoryList(&L) 销毁线性表,且释放内存
  • void ListInsert(&L, i, e) 插入操作,在表中第i个元素插入指定元素e
  • Type ListDelele(&L, i) 删除操作,删除L表中第i个位置的元素,并用e返回元素的值
  • LocateElem(L, e) 按值查找操作,在表L中查找具有给定关键字值的元素
  • GetElem(L, i): 按位查找操作,获取表L中第i个元素的值

其它常用操作:

  • Length(L):求表长,返回线性表的长度,即L中数据元素的个数
  • PrintList(L): 输出操作,按前后顺序输出线性表L中所有元素的值
  • Empty(L): 判空操作,若L为空表,则返回True,否则返回False

Tips

  1. 对数据的操作:创建销毁、增删改查

  2. C语言函数定义要清楚(上述是抽象接口)

  3. 实际开发中,可根据实际需求定义其它操作

  4. 函数名和命名形式都可以改变

  5. &(引用,要知道这是啥,就是要修改调用的参数,要知道引用是C++的概念, C语言这么写↓,即根据地址访问元素,而不是单纯修改形参)

    • #include <stdio.h>
      
      void test1(int x){
      	x = x + 1;
      }
      
      void test2(int* x){
      	*x = *x + 1;
      }
      
      int main(){
      	int x = 0;
      	test1(x);
      	printf("%d\n", x);
      	test2(&x);
      	printf("%d", x);
      	return 0;
      }
      
Why?要实现线性表的基本操作?
  1. 团队合作编程,你定义的数据结构要方便别人的使用(封装)
  2. 将常用的操作(运算)封装成函数,避免重复工作,降低出错风险。

顺序表(顺序存储)——逻辑结构

逻辑上相邻的元素,内存里也相邻,每个数据元素所占空间一样大

如何知道一个数据元素大小?

  • C语言sizeof(ElemType)
    • eg:sizeof(int) = 4B
顺序表的实现——静态分配
// 注意,只能以这种方式定义常量
// int x = 10;
// int a[x];
// 这种定义形式是错误的
#define Maxsize 10
typedef struct {
    ElemType data[Maxsize];  //EmemType: 数据类型(int、、、)
    int length;
} SqlList;
  • 如果“数组”长度满了怎么办?
    • 放弃治疗,因为这种方式一旦分配满了就不能更改
    • 如果一开始分配太长,又浪费空间
顺序表的实现——动态分配
#define InitSize 10
typedef struct {
	ElemType *data;  // 指示动态分配数组的指针
	int MaxSize;
	int Length;
} SqlList;

Tips

C语言中存在malloc, free函数

malloc申请一整片连续的存储空间

malloc函数返回一个指针,需要强制转换为你定义的数据元素类型的指针

L.data = (ElemType *) malloc (sizeof (ElemType) * InitSize);
顺序表的实现

顺序表的特点

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

在第i个位置的元素插入元素e,i及i之后的元素后移,第i个元素变为e

时间复杂度:

  • 最好复杂度:O(1)
  • 最坏复杂度:O(n)
  • 平均复杂度:O(n)
顺序表的基本操作——删除

删除第i个地方的元素,并返回该元素

时间复杂度:

  • 最好复杂度:O(1)
  • 最坏复杂度:O(n)
  • 平均复杂度:O(n)
顺序表的基本操作——按位查找

直接返回第i个元素

时间复杂度:O(1)(随机存取的特性)

顺序表的基本操作——按值查找

在表中查找具有给定关键字值的元素

注意:C/C++的结构体不能使用“==”进行比较

C++可以重载操作符

时间复杂度:

  • 最好:O(1)
  • 最差:O(n)
  • 平均:O(n)

附:静态顺序表代码:

// 静态顺序表的实现
#include <stdio.h>

#define Maxsize 10

typedef struct {
    int data[Maxsize];
    int length;
} SqlList;

// 初始化
void Init(SqlList *l) {
    (*l).length = 0;
    for (int i = 0; i < Maxsize; i++) {
        (*l).data[i] = 0;
    }
}

//增添长度建议直接放弃治疗

// 插入, 返回0:插入失败;返回1:插入成功
int ListInsert(SqlList *l, int i, int e){
    if (i < 1 || i > (*l).length + 1) return 0;
    if ((*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 ++;
    return 1;
}

// 删除,返回0:删除失败;否则返回删除值
// 注意:这里不考虑删除元素为0的情况!!!
int ListDelete(SqlList *l, int i){
    if (i < 1 || i > (*l).length) return 0;
    int temp = L.data[i - 1];
    for (int j = i; j < (*l).length; j++)
        (*l).data[j - 1] = (*l).data[j];
    l.length --;
    return temp;
}

// 按位查找 返回0:查找失败;否则返回元素值
// 注意:这里不考虑元素为0的情况!!!
int GetELem(SqlList l, int i){
    if (i < 1 || i >= l.length) return 0;
    return l[i - 1];
}

// 按位查找 返回0:查找失败;否则返回元素位置
int LocateElem(SqlList l, int e){
    for (int i = 0; i < l.length; i++)
        if (l.data[i] == e)
            return i + 1;
    return 0;
}

//打印顺序表
void PrintList(SqlList l){
    for (int i = 0; i < l.length; i++){
        printf("%d ", l.data[i]);
    }
}



int main() {
    SqlList l;
    Init(&l);
    PrintList(l);
    return 0;
}

动态顺序表代码:

// 静态顺序表的实现
#include <stdio.h>
#include <malloc.h>

#define InitSize 10

typedef struct {
    int *data;  // 数据
    int length; // 当前长度
    int maxsize;  // 最大容量
} SqlList;

// 初始化
void Init(SqlList *l) {
    (*l).length = InitSize;
    (*l).maxsize = InitSize;
    (*l).data = (int *) malloc (sizeof (int) * (*l).maxsize);
    for (int i = 0; i < (*l).maxsize; i++) {
        (*l).data[i] = 1;
    }
}

//增添长度
void IncreaseList(SqlList *l, int add_length){
    int *p = (*l).data;
    (*l).data = (int *) malloc(sizeof (int) * ((*l).maxsize + add_length));
    (*l).maxsize += add_length;
    for (int i = 0; i < (*l).maxsize; i++){
        if (i < (*l).length) (*l).data[i] = p[i];
        else (*l).data[i] = 0;
    }
}

//打印顺序表
void PrintList(SqlList l){
    for (int i = 0; i < l.length; i++){
        printf("%d ", l.data[i]);
    }
}



int main() {
    SqlList l;
    Init(&l);
    IncreaseList(&l, 5);
    PrintList(l);
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤赤赤赤赤赤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值