数据结构看书笔记_线性表_顺序存储结构
目录
线性表的定义
线性表(List): 零个或者多个数据元素的有限序列
注意: 序列说明元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有,且只有一个前驱和后继,
是有限的,事实上,计算机处理的对象都是有限的
线性表抽象数据结构定义
前面给出了线性表的定义,现在分析一下线性表应该有哪些操作:
首先线性表中的元素类型都是一样的,
对表进行操作那首先得创建表, 没有元素就是空表,然后往里边填数据元素-初始化, 有些数据需要查找,有些不合适需要删除,也可以往里边增加数据
于是线性表的抽象数据类型定义如下:
ADT线性表(List)
Data
线性表中的数据对象集合为{a1,a2,....,an},每个数据元素的类型均为DataType.其中除了第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个后继元素.数据元素之间的关系是一对一的关系
Operation
InitList( *L ): 初始化操作,建立一个空的线性表L
ListEmpty(L): 若线性表为空,返回ture, 否则返回false
ClearList(*L): 将线性表清空
GetElem(L, i, *e): 将线性表L中的第i个元素值返回给e
LocateElem(L, e): 在线性表中查找与给定值e相等的元素,若查找成功返回该元素在表中的序号表示成功;否则返回0表示失败
ListInsert(*L, i, e): 线性表中L中第i个位置插入新元素e
ListDelet(*L, i, *e): 删除线性表中第i个位置元素,并用e返回其值
ListLengeh(L): 返回线性表L的元素个数
endADT
线性表的顺序存储结构
上面介绍了线性表的抽象数据类型,现在介绍一下其俩种物理结构中的第一种--顺序存储结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素,线性表的顺序存储示意如下:
从上面的示意图可以看出,线性表的顺序存储结构,其实就是一个一维数组,在内存中找块地儿,通过占位的形式,把一定的内存空间给占了,然后将相同的数据元素依次存放在这块空地中,
那么我们可以给出线性表的顺序存储的结构代码:
#define MAXSIZE 20 //存储空间的初始分配量 typedef int ElemType; //ElemType是线性表中元素的类型 typedef struct { ElemType data[MAXSIZE]; //数据存储结构元素,最大空间为MAXSIZE int length; //线性表当前长度 }SqList;
这里可以发现顺序存储结构需要三个属性:
-
存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置
-
线性表的最大存储容量: 数组长度MAXSIZE
-
线性表当前长度: length
数据元素和存放它的数组下标之间存在对应关系.如下图
用数组存储顺序意味着要分配固定长度的数组空间,由于线性表中可以进行插入和删除操作,于是分配的数组空间是要大于等于当前线性表的长度
存储器中的每个存储单元都有自己的编号,这个编号称为地址,之间有如下关系(LOC表示获得存储位置的函数)
LOC(ai+1) = LOC(ai) + c
LOC(ai) = LOC(a1) + (i-1)*c
通过这个公式可以随意算出线性表中任意位置的地址,而且都是相同的时间,无论在线性表中存入还是取出数据,从时间复杂度来说就是O[1], 对于这种时间复杂度是O[1]的存储结构称为随机存取结构
顺序存储结构的插入与删除
对于线性表的顺序存储结构来说,如果要实现GetElem操作,只需将其第i个位置元素值返回,也就是下标是i-1的值返回就可:
#define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int Status; /* Status是函数的类型,其值是函数结果状态的代码 */ /* 初始条件: 顺序线性表L已存在,1<=i<=Length */ /* 操作结果: 用e返回L中第i个数据元素的值 */ Status GetElem(SqList L, int i, ELemType *e) { if(L.length == 0 || i<1 || i>L.length) return ERROR; *e = L.data[i-1]; return OK; }
插入操作
ListInsert
思路:
-
由于需要对线性表进行操作,所以需要进行指针操作
-
如果插入位置不合理,输出异常
-
如果线性表当前长度大于等于数组长度,输出异常,或者动态增加容量
-
从最后一个元素开始遍历到第i个位置,分别将他们都向后移动一个位置
-
将要插入的元素填入位置i中
-
表长+1
代码在后面
删除操作
ListDeldte
思路:
-
如果删除位置不合理,输出异常
-
取出删除元素
-
从删除元素位置开始遍历到最后一个元素的位置,分别将他们都向前移动一个位置
-
表长+1
平均操作次数:(n-1)/2 插入和删除时间复杂度: O[n]
存,读时间复杂度:O[1]
由此可见顺序线性表比较适合元素个数不怎么变化,而更多是存取数据的应用
顺序存储结构的优点和缺点
-
优点:
1. 无须为表示表中之间的罗技关系而增加额外的存储空间
2. 可以快速得存取表中任一位置的元素
-
缺点
1. 插入和删除操作需要移动大量的数据
2. 当线性表长度变化较大时候,难以缺点存储空间的容量
代码
main.c
/* main.c */
#include <stdio.h>
#include "List.h"
int main()
{
ElemType a,b,c;
int g,i,d;
SqList L = {{1,2,3,4,5,6},6};
ScanList(L);
/* 查询一个线性表单元 */
printf("Get_number: ");
scanf("%d", &g);
GetELem(L, g, &a);
printf("Get_Elem : %d\n",a);
/* 插入一个线性表单元 */
printf("Insert_number:");
scanf("%d", &i);
printf("Insert_data:");
scanf("%d", &b);
ListInsert(&L, i, b);
ScanList(L);
/* 删除一个线性表单元 */
printf("Delete_number:");
scanf("%d", &d);
ListDelete(&L, i, &c);
ScanList(L);
printf("delete data: %d\n", c);
return 0;
}
List.c
/* List.c */
#include <stdio.h>
#include "List.h"
/* 从线性表L中取出第i个元素,并用e返回 */
Status GetELem(SqList L, int i, ElemType *e)
{
if(L.length==0 || i<1 ||i>L.length)
return ERROR;
*e = L.data[i-1];
return OK;
}
/* 遍历一个线性表L */
void ScanList(SqList L)
{
int i;
for(i=0; i<L.length; i++)
printf("%d\n",L.data[i]);
}
/* 从线性表L中第i个位置之前插入数据元素e */
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if(L->length == MAXSIZE) return ERROR;
if(i<1 || i>L->length+1) return ERROR;
if(i<=L->length)
{
for(k=L->length-1; k>=i-1; k--)
L->data[k+1] = L->data[k];
}
L->data[i-1] = e;
L->length++;
return OK;
}
/* 从线性表L中第i个位置删除数据元素,用e返回其值 */
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if(L->length == 0) return ERROR;
if(i<1 || i>L->length+1) return ERROR;
*e = L->data[i-1];
if(i<=L->length)
{
for(k=i; k<=L->length; k++)
L->data[k-1] = L->data[k];
}
L->length--;
return OK;
}
List.h
#ifndef _LIST_H_
#define _LIST_H
#define MAXSIZE 20
#define OK 1
#define ERROR 0
#define TURE 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int length;
}SqList, *pSqList;
Status GetELem(SqList L, int i, ElemType *e);
void ScanList(SqList L);
Status ListInsert(SqList *L, int i, ElemType e);
Status ListDelete(SqList *L, int i, ElemType *e);
#endif
输出结果如下:
上一篇: 新浪微博某分站SQL注入一枚
下一篇: TCP/IP协议簇下的各报文结构总结