数据结构——线性表

(自用,侵删)

线性结构基本特点:除第一个元素无前驱,最后一个元素无后继外,其他所有元素都有一个前驱和一个后继

线性表是最常用的一种线性结构

线性表:由n个数据特性相同的元素构成的有限序列

顺序表

线性表的顺序存储表示:用一组地址连续的存储单元依次存储线性表的数据元素

                    LOC(a_{i})=LOC(a_{1})+(i-1)*l

随机存取

//顺序表存储结构
#define MAXSIZE 100
typedef struct
{
ElemType *elem;//存储空间基地址,ElemType为元素类型
int length;
}SqList;//顺序表结构类型为SqList
稀疏矩阵顺序存储结构类型定义
#define MAXSIZE 100

typedef struct
{
float coef;//系数
int expn;//指数
}Polynomial;

typedef struct
{
Polynomial *elem;//存储空间基地址
int length;
}SqList;

【例】图书数据顺序存储类型

#define MAXSIZE 1000

typedef struct

{

char no[30];//书编号

char name;[50]//书名

float price;//图书价格

}Book;

typedef struct

{

Book *elem;

int length;

}SqList;

通过L.elem[i-1]访问表中位置序号为i的图书记录

基本操作

初始化

Status InitList(SqList &L)
{
L.elem=new ELemtype[MAXSIZE]
if(L!=elem) exit(OVERFLOW);
L.length=0;
return Ok;
}

取值

Status GetElem(SqList L,int i,Elemtype &e)
{
if(i>L.length||i<1)
return ERROR;
e=L.elem[i-1];
return OK;
}

插入

Status ListInsert(SqList &L,int i,Elemtype e)
{
int j;
if((i>L.length+1)||(i<1))return ERROR;
if(j=L.length) return ERROR;//j为链表中第j个位置
for(j=L.length,j>i,j--)
L.elem[j]=L.elem[j-1];
L.elem[i-1]=e;
L.length++;
return OK;
}

删除

链表

任意存储单元存储线性表的元素

顺序存取

存储本身的信息和直接后继的信息,组成了数据元素的存储映像,称为结点,

包括数据域,指针域

指针或链:指针域中存储信息

线性链表或单链表:链表中每个结点只包含一个指针域的结点

链式映像或非顺序映像:数据元素逻辑相邻物理位置不紧邻的数据结构

//单链表每个结点的存储结构
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;//LinkList为指向结构体的指针类型

首元结点:链表中存储第一个数据元素的结点

头结点:首元结点前附设的一个结点,可以不存储任何信息,也可以存储与数据元素类型相同的其他附加信息(如,当数据元素为整数型时,头结点的数据域可存放该头结点的长度)

其指针域保存首元结点的的地址,元素操作与其他结点相同(元素类型相同)

L为空指针,链表为空时,不设头结点,L==NULL,设头结点,L->next==NULL

头指针:指向链表的第一个结点的指针(设头结点指向头结点,不设指向首元结点)

基本操作

初始化

Status InitList(LinkList &L)
{
L=new LNode;//生成头结点,头指针L指向头结点
L->next=NULL;
return OK;
}

取值

Status GetElem(LinkList &L,int i,ElemType &e)
{
p=L-next;//-
int j;
while(p&&j<i)
{
p=p->next;
j++;
}
if(!p||p>i)return ERROR;
e=p->data;
return OK;
}

按值查找

LNode *LocateElem(LinkList &L,ElemType e)
{
p=L->next;
int i=1;
while(p&&p->data!=e)
p=p->next;
return p;
}

插入

插入到结点i的位置,即a_{i}之前的位置(注:此函数为两个元素之间插入)

Status ListInsert(LinkList &L,int i,ElemType e)
{
p=L;
int j=0;
/*
s=new LNode;
q=new LNode; 
while(p&&j<i)
{
q=p;
p=p->next;
j++;
}
q->next=s;
s->next=p;
s->data=e;
return Ok;*/此段代码冗余

while(p&&j<(i-1)) 
{
p=p-next;
j++;
}
if(!p||j>i-1)
return ERROR;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}

删除

循环链表     

表中最后一个结点的指针域指向头结点 

指向表尾结点判别条件
   无头结点有头结点

单链表        

   p!=NULL p->next!=NULL
循环单链表    p!=L         p->next!=L

将两个表合并为一个表:

p=B->next->next;

B->next=A->next;

A->next=p;

双向链表

//双向链表的存储结构

插入

删除

顺序表和链表的比较

空间性能
是否需要预先分配存储空间 
顺序表不需要
链表需要

存储密度大小

存储密度=数据元素本身占用的存储量 / 节点结构占用的存储量

顺序表:100%(不考虑空闲区),单链表:50%

为节约空间,长度变化不打时采用顺序表

时间性能
存储元素插入和删除
顺序表O(1)O(n)
链表O(n)O(1)

线性表的应用

线性表的合并
有序表的合并

有序表:数据元素相互可比较,且依值非递增或非递减有序排列的线性表

顺序有序表

链式有序表

习题

1.1二叉树顺序存储结构比链式存储结构节省存储空间      ×

对于完全二叉树顺序存储结构可以比链式存储结构节省空间,链式存储结构不会浪费存储空间,但对于大规模的二叉树会占用大量的指针空间

2.1如果线性表最常用的操作是在最后一个元素之后插入一个元素,和删除第一个元素,采用仅有尾指针的单循环链表存储方式最节省运算时间

2.2最后一个结点后插入一个结点或删除最后一个结点:带头结点的双循环链表带尾指针的双循环链表

2.3存取第一个元素和前驱后继的值:线性表

2.4静态链表中指针表示的是下一元素在数组中的位置

静态链表类似于数组,需要预先分配存储空间,在插入和删除时最为方便只需要修改指针,动态链表在需要时才申请内存空间(通过molloc或free函数),空间利用率高

2.5单链表中指针p指向其中某个结点,在该结点前插入一个由指针s指向的结点,无法通过已知条件实现

在结点前插入必须知道该结点前驱结点的指针

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值