一、线性表的逻辑定义和性质

线性表是最简单和最常用的一种数据结构,他是由n个数据元素(结点)a1,a2,a3,a4........an组成的有限序列。其中,数据元素个数那位表的长度。当n为0时称为空表,非空的线性表通常记为 (a1,a2,a3,a4........ai-1,ai,..........an)

这里的元素ai(0< i < n+1) 是一个抽象的符合,他可以是一个数或者一个符合,还可以是较复杂的记录。

从线性表的定义可以看出呀的逻辑特征,对于一个非空的线性表:

(1)有且仅有一个称为开始元素的a1,它没有前驱,仅有一个直接的后继a2

(2)有且仅有一个称为终端元素的an,它没有后继,仅有一个直接前驱an-1

(3)其余元素ai(1< i <n)称为内部元素,他们都有且仅有一个直接前驱ai-1和一个直接后继ai+1

二、线性表上的定义和基本运算

(1)对于线性表InitList(L),构造一个空的线性表L

(2)求表长ListLength(L),返回线性表L中元素的个数,即表长

(3)取表中第i个元素GetNode(L,i),若 0<i<ListLength(L)+1,则返回第i个元素ai

(4)按值查找LocateNode(L,x),在表L中查找第一个值为x的元素,并返回该元素在表L中的位置,若表中没有元素的值为x,则返回0值

(5)插入 InsertList(L,i,x),在表L的第i个元素之前插入一个值为x的新元素,表L的长度加1

(6)删除 DeleteList(L,i),删除表L的第i个元素,表L的长度减1

二、线性表的两种实现方式

1.1顺序表示(顺序表)

概念:用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构的线性表称为顺序表。

特点:逻辑上相邻的数据元素,物理次序也是相邻的。

只要确定好了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的储存结构,因为高级语言中的数组类型也是有随机存取的特性,所以通常我们都使用数组来描述数据结构中的顺序储存结构,用动态分配的一维数组表示线性表。

1.2 代码实现

以最简单的学生信息管理为例:

首先先创建两个数据结构,如下:

#define maxsize 100 //定义学生最大数量
#define OK 1       //正确标志
#define ERROR 0     //失败标志
//学生信息的数据结构
typedef struct{int id;   //学生idchar name[30];   //学生姓名
}Student;//顺序表数据结构
typedef struct{Student *elem;   //储存空间的基地址int length;      //数据结构的长度
}SqList;//定义SqList类型的变量
SqList L;

这是一个十分简单的例子,这样我们就可以通过L.elem[i-1]访问序号为i的学生信息了。其实这里我们用到了指针数组。如果你对指针数组还不熟悉的话,可以去另一篇文章看看:https://blog.csdn.net/qq_38378384/article/details/79951651

1.初始化

基本算法:

   //初始化顺序表基本算法Status InitList(SqList &L){//构造一个空的顺序表LL.elem = new ElemType[maxsize];  //分配内存空间if(!L.elem) exit(-1);L.length = 0;return OK;}

2.取值

基本算法:

//顺序表取值Status Get(SqList &L,int i,ElemType &e) {if(i<1||i>L.length)  return ERROR;e = L.elem[i-1];return OK;       }

3.查找

基本算法:

//顺序表查找int Find(SqList L,ElemType e) {//查找值为e的数据元素,返回其序号for(i=0;i<L.length;i++){if(L.elem[i]==e) return i+1;}return ERROR;   //查找失败   }

4.插入

基本算法:

//顺序表插入Status ListInsert(SqList &L,int i,ElemType e){if((i<1)||(i>L.length+1)) return ERROR;  //i不合法if(L.length == maxsize) return ERROR;  //满了for(j=L.length-1;j>=i-1;j--)L.elem[j+1]=L.elem[j]; //将第n个至i个位置的元素后移L.elem[i-1]=e; //将e放进第i个位置}

5.删除

基本算法:

 //顺序表删除Status ListDelete(SqList &L,int i){//删除第i个元素,i的值为[1,L.length]if((i<1)||(i>L.length)) return ERROR;for(j=i;j<=L.length-1;j++)L.elem[j-1]=L.elem[j];--L.length;  //长度减一return OK;}

算法都十分的简单,眼尖的你可能发现了,为啥有的参数用的是引用,有的不是呢?

这里我就得讲下使用引用作为形参的作用了,主要有三点:

(1)使用引用作为参数与使用指针作为参数的效果是一样的,形参变化时实参对应也会变化,这个我在上篇文章(我上面给的链接)也有说明,引用只是一个别名。

(2)引用类型作为形参,在内存中并没有产生实参的副本,而使用一般变量作为形参,,形参和实参会分别占用不同给的存储空间,当数据量较大时,使用变量作为形参可能会浪费时间和空间。

(3)虽然使用指针也可以达到引用一样的效果,但是在被调函数中需要重复使用"*指针变量名"来访问,很容易产生错误并且使程序的阅读性变差。

此时你会发现,使用顺序表作为存储时,空间是一次性直接开辟的,所以可能会有空间不足或者浪费空间的情况出现,那么为啥不用一个就分配一个空间呢,再使用一个方式将这些空间串起来不就好了,是时候展现真正的技术了(链表)。

2.1链表

概念:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),包括数据域和指针域,数据域存数据,指针域指示其后继的信息。

这里重点讲单链表,如图:

2.1代码实现

//单链表存储结构typedef struct LNode{ElemType data;   //数据域struct LNode *next; //指针域}LNode,*LinkList;

为了提高程序的可阅读性,在此对同一结构体指针类型起了两个名称,LinkList与LNode*,本质上两者是等价的。通常习惯上用LinkList定义单链表,强调定义的是某个单链表的头指针,用LNode *定义指向单链表中任意结点的指针变量。

例如,定义LinkList L,则L为单链表的头指针,若定义LNode *p ,则p为指向单链表中某个结点的指针,用*p代表该结点。

1.初始化

基本算法:

//初始化 Status InitList(LinkList &L){//构造一个单链表L=new LNode;  //生成头结点,用头指针L指向头结点L->next =NULL;  return OK;     }

2.取值

基本算法:

//取值Status Get(LinkList L,int i,ElemType &e) {//在带头结点的单链表L中根据序号I获取元素的值,用e返回L中第i个数据元素的值p=L->next;j=1;//计数器while(p&&j<i)     {  //顺着链表向后扫描,直到j==ip=p->next;++j;}if(!p||j>i) return ERROR; //不合法e=p->data;   //找到该结点后获取该结点的数据域return OK; }

3.查找

基本算法:

//查找LNode *Find(LinkList L,ElemType e) {p=L->next; //使p指向首元结点while(p && p->data!=e){p=p->next;  //不符合条件就一直滚下去}return p;   //这里有两种情况,找到的时候返回指针p,如果找不到那么这个p则为null,因为最后一个指向的是null}

4.插入

基本算法:

//插入
Status ListInsert(LinkList &L,int i,ElemType e){//在带头结点的单链表L中第i个位置插入值为e的新结点p=L;j=0;while(p&&(j<i-1)){p=p->next;         //查找第i-1个结点,p指向该结点++j;}if(!p||j>i-1) return ERROR;s=new LNode;   //生成一个新结点s->data=e;   //将结点*s的数据域置为es->next=p->next; //先接尾部p->next=s;  //再接头部
}

5.删除

基本算法:

//删除
Status ListDelete(LinkList &L,int i){//删除第i个元素p=L;j=0;while((p->next)&&(j<i-1)){p=p->next;    //查找i-1个结点++j;}if(!(p->next)||(j>i-1)) return ERROR;  //当i>n或i<1时,不符合条件q=p->next;   //临时保存被删除的地址p->next=q->next;  //将前驱结点指向后驱delete q;  //释放删除结点的空间return OK;
}

其实单链表可以想象成一列人在玩游戏,每个人都把手搭到后面那个人的肩膀上,每个人身上都有一个大口袋用来放数据,最后一个人没人可以搭就一直悬空着,第一个带头领队的就不用口袋了,它是一个头结点,是用来找到第一个有口袋的人的,也就是首元结点。

这样想的话就简单了,初始化的时候就是用一个人当头结点,它没有口袋,他的手是用来搭到第一个有口袋的人肩膀的,因为这个人还没来,所以它的next是Null,而取值时,通过参数i,我们就可以从首元结点开始数,数到第i个人,找到他后,就可以拿他口袋里面的东西,查找是知道口袋里面东西是什么,想找到这个东西的拥有者,也是一样从首元结点开始找。遍历下去,插入的话,比如要插入第i个位置,那么我们就先找到第i-1个人,然后让新来的手搭到第i个人身上,然后再让第i-1个人把之前放在第i个人的手挪开,放在新来的人的肩膀上,删除操作的话,例如删除第i个人,那么也是先找到第i-1个人,这里的重点是,因为链表的查询只能是从头开始找的,是不能逆回去的,所以我们需要找个变量把要删的那个人的地址先存起来,然后把第i-1个的手放到第i+1个人身上,如果我们不找个变量把那个人的地址存起来,这时候我们就没办法找到他了,因为我们用一个变量临时保存他的地址,于是我们只需要释放这个地址的空间就可以了。

这就是单链表的基本操作,那么如何创建单链表呢?

主要有着两种方法(前插法和后插法)

//前插法创建单链表

 void CreateList(LinkList &L,int n) {//逆次序输出n个元素的值L=new LNode;L->next=NULL;for(i=0;i<n;++i) {p=new LNode;  //生成新结点cin>>p->data;  //输入新结点的数据域内容p->next=L->next; //将新结点插到头结点之后L->next=p;}}

//后插法

void CreateList(LinkList &L,int n){//正次序输入n个元素的值L=new LNode;L->next=NULL;  //建立一个带头结点的空链表r=L;   //尾指针r指向头结点for(i=0;i<n;++i) {p=new LNode; //生成新结点cin>>p->data; //输入新结点的数据域内容p->next=NULL;r->next=p;  //将新结点插入尾结点之后r=p;   //改变尾指针,使其指向新的尾结点}}

两种方式的结果是一样的,区别就是前插法是把新的元素插到最前面,代替了首元结点的位置,就是明摆的插队,而后插法是插到最后面,有点类似于队列。而且后插法多了一个用来指向尾结点的尾指针。

实际上链表还有两种,双向链表和循环链表,循环链表用的比较多,就是把头和尾连起来了,像一个圈一样。这里我就不说明了,因为只要懂了单链表,另外两种理解起来是十分容易的事情。

线性表的定义和基本运算之线性结构相关推荐

  1. 一、线性表的顺序存储和基本运算

    线性表的顺序存储: 线性表的顺序存储指的是将线性表的数据元素按其逻辑次序依次存入一组地址连续的单元里,用这种方法存储的线性表称为顺序表. 只要确定线性表存储的起始位置,线性表中任意一个元素都可以随机存 ...

  2. 2.1 线性表的定义和基本操作

    目录 思维导图 线性表的定义 线性表的基本操作 思维导图 数据结构的三要素:逻辑结构.数据的运算.存储结构. 线性表的定义 线性表的基本操作

  3. c语言实现线性表的算法,数据结构算法代码实现——线性表的定义(一)

    线性表的定义 线性表:是最常用且最简单的一种数据结构,它是一种线性数据结构,是由类型相同的n个(n≥0)数据元素组成的有序序列. 线性表的特点:有且只有一个被称作"第一个"的数据元 ...

  4. (王道408考研数据结构)第二章线性表-第一节:线性表的定义和基本操作

    文章目录 一:线性表的定义 二:线性表的基本操作 一:线性表的定义 线性表(Linear List):零个或多个数据元素的有限序列 元素之间是有顺序的 若元素存在多个,则第一个元素无前驱,最后一个元素 ...

  5. 数据结构(C语言)——线性表(定义,基本操作)

    数据结构(C语言)--线性表(定义,基本操作) 一. 线性表的定义 二.线性表的基本操作 什么时候要传入引用"==&=="----对参数的修改结果需要"==带回来 ...

  6. 脚踏实地《数据结构第二章》第一节:线性表的定义和基本操作

    考点分析 一:线性表的定义(数据结构三要素–逻辑结构) 定义:线性表是具有相同数据类型的n(n>0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表. 相同:每个数据元素所占空间一 ...

  7. 线性表的定义与特点及抽象数据类型定义

    一.线性表的定义 由n(n>=0)个数据特性相同的元素构成的有限序列称为线性表. 线性表中元素的个数n(n>=0)定义为线性表的长度,n=0时线性表称为空表. 二.非空线性表及线性结构的特 ...

  8. 数据结构摧毁线性表用c语言,[简述]数据结构-线性表(c语言实现)

    [简述]数据结构-线性表(c语言实现)second60 20180422 1. 线性表的定义 线性表是具有相同特性的数据元素的一个有限序列. 2. 线性表抽象数据类型描述 ADT  List { 数据 ...

  9. 数据结构之线性表——(二、链式存储结构)[c语言]

    数据结构之线性表--(二.链式存储结构-单链表) 链式存储结构以及基本运算的实现 背景:由于线性表的存储特点是用物理上的相邻实现逻辑上的相邻,他要求用连续的存储单元顺序存储线性表中的各个元素,所以,对 ...

最新文章

  1. Oracle查询锁表以及杀会话或系统进程来解除锁表操作
  2. 【Python】青少年蓝桥杯_每日一题_9.03_画三角形和半圆相切
  3. 【Python基础】当变量有值时,为什么会出现UnboundLocalError?
  4. MySQL【问题记录 01】报错 1709 - Index column size too large. The maximum column size is 767 bytes. 可能是最简单的方法
  5. linux网络存储服务器选题意义,基于嵌入式Linux的网络存储的实现和研究
  6. 词法、语法与语义相关知识
  7. 禾川触摸屏编程软件_汇川PLC编程PLC代写程序
  8. Flask Web表单
  9. 关于argc和argv的输出
  10. for命令不跳过空白行_Java程序员必备:查看日志常用的linux命令
  11. python 如何边改代码边调试_Python 代码调试神器:PySnooper
  12. Linq GroupJoin 使用
  13. VC++ CString互转double
  14. mongoose 执行删除操作的坑
  15. redis-数据类型-string类型
  16. 【华为云技术分享】敏捷DevOps知识卡大全(内附下载资料)
  17. mysql5.7存储过程实例_MySQL 存储过程简单实例
  18. 小程序mysql+php测试,莲米粒是一个基于PHP+MySQL+微信小程序技术栈
  19. 如何设置内网打印机端口网络穿透到公网
  20. Retrofit自定义CallAdapterFactory

热门文章

  1. pin码计算器网页版_AP微积分Excel简便计算+网页工具指南
  2. python 异常回溯_关于python:在循环中捕获异常回溯,然后在脚本末尾引发错误...
  3. jop怎么读音英语怎么说_“跨年”英语怎么说?
  4. 【工具】Jupyter Notebook介绍
  5. AWS DevOps – 配合Jenkins和CodeDeploy实现代码自动化部署
  6. 面向对象初调用:foolish 电梯
  7. ES6中object对象属性
  8. jQuery特效手风琴特效 手写手风琴网页特效
  9. [转帖]ISE与Modelsim联合观察中间信号
  10. 图像处理基本算法-形态学