前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据结构与算法笔记 cp2-1:线性表

数据结构与算法笔记 cp2-1:线性表

作者头像
Chor
发布2019-11-07 18:10:14
4020
发布2019-11-07 18:10:14
举报
文章被收录于专栏:前端之旅前端之旅

线性表

1.1 定义:

List,由零个或多个数据特性相同的元素构成的有限序列。个数 n 称为线性表的长度,n=0 的时候称为空表。比如说,十二星座就是一个线性表,它的“第一个”和“最后一个”元素都是唯一的,并且中间的元素均只有一个前驱、一个后继。

1.2 抽象数据类型

代码语言:javascript
复制
ADT List{
    Data:.......
    Operation:
        InitList(&L): 初始化,建立一个空的线性表L
        ClearList(&L): 清空线性表L
        GetElem(L,i,&e): 将L中第i个位置元素值返回给e
        LocateElem(L,e): 在L中查找与e相等的元素
        ListInsert(&L,i,e): 在L中第i个位置插入新元素e
        ListDelete(&L,i,&e): 删除L中第i个位置元素,并用e返回其值
        ListLength(L): 返回L长度
} ADT List

线性表的顺序存储结构 / 顺序表

2.1 定义:

指的是用一段地址连续的存储单元依次存储线性表的数据元素。

各个元素的地址之间构成等差数列,因此,知道了某一个元素的地址,就可以随时推导出其它元素的地址,也就是说不管取出还是存入哪一个元素,花费的时间都一样,是一个常数(O(1)),这种特性的存储结构就叫随机存取结构

一维数组可以实现线性表的顺序存储结构,不过要注意数组下标从0开始,而说线性表的时候说的是位序,是从1开始的。

2.2 基本操作

(1) 初始化:

首先定义线性表顺序存储结构:

代码语言:javascript
复制
typedef struct Table{
    int * head;//声明了一个名为head的长度不确定的数组,也叫“动态数组”
    int length;//记录当前顺序表的长度
    int size;//记录顺序表分配的存储容量
}table;

第一个操作是初始化,包括:给head申请足够大小的物理空间;给size和length赋初值:

代码语言:javascript
复制
#define Size 5 //对Size进行宏定义,表示顺序表申请空间的大小
table initTable(){
    table t;
    t.head=(int*)malloc(Size*sizeof(int));//构造一个空的顺序表,动态申请存储空间
    if (!t.head) //如果申请失败,作出提示并直接退出程序
    {
        printf("初始化失败");
        exit(0);
    }
    t.length=0;//空表的长度初始化为0
    t.size=Size;//空表的初始存储空间为Size
    return t;
}

(2) 取值: 找某一个位序的元素,只需要判断位序的合法性,之后返回数组[位序-1]即可。

(3) 查找/修改: 遍历数组元素,与目标元素比较,相等则返回。如果要修改,重新赋值即可。

(4) 删除: 找到目标元素,让后续元素整体前移一个位置,之后长度减一即可。

代码语言:javascript
复制
table delTable(table t,int add){
    if (add>t.length || add<1) {
        printf("被删除元素的位置有误");
        exit(0);
    }
    //删除操作
    for (int i=add; i<t.length; i++) {
        t.head[i-1]=t.head[i];
    }
    t.length--;
    return t;
}

比如说要删除5个元素中的第三个,那么 add 就是 3,而 t.head[3] 就是第四个元素,从这个元素开始依次向前移动并覆盖前面的元素。

(5) 插入: 找到目标位置,将该位置对应元素以及后续元素整体后移一个位置,之后长度加一即可。

代码语言:javascript
复制
//插入函数,其中,elem为插入的元素,add为插入到顺序表的位置
table addTable(table t,int elem,int add)
{
    //判断插入本身是否存在问题
    if (add>t.length+1||add<1) {
        printf("插入位置有问题");
        return t;
    }
    //线性表长度等于数组长度,没有多余空间容纳新插入的元素,此时需要申请
    if (t.length==t.size) {
        t.head=(int *)realloc(t.head, (t.size+1)*sizeof(int));
        if (!t.head) {
            printf("存储分配失败");
            return t;
        }
        t.size+=1;
    } 
    for (int i=t.length-1; i>=add-1; i--) {
        t.head[i+1]=t.head[i];
    }
    t.head[add-1]=elem;
    t.length++;
    return t;
}

  • 首先要注意范围的判断,add 作为目标位置,至少也得等于1,此时是插在最前面;同时,add 可以等于 length+1,此时是插在最后面,但不能比 length+1 更大了,否则会出现空隙。
  • 接着要注意是从后往前遍历的,因为如果是从前往后的话就会发生覆盖。
  • 可以不做“目标位置是否在表尾”的判断,这样会直接绕过for循环,执行赋值。

这里可以发现,线性表的插入和删除元素操作往往需要移动大量的元素。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线性表
    • 1.1 定义:
      • 1.2 抽象数据类型
      • 线性表的顺序存储结构 / 顺序表
        • 2.1 定义:
          • 2.2 基本操作
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档