数据结构2_线性表

2 线性表

线性结构,线性结构的特点:(1)是数据元素的非空有限集合;(2)存在唯一的一个被称做“第一个”的数据元素;(3)存在唯一的一个被称做“最后一个”的数据元素;(4)除第一个以外,集合中的每个数据元素均有一个前驱;(5)除最后一个以外,集合中的每个数据元素均有一个后继;

2.1 线性表的类型定义

线性表示最常用也是最简单的数据结构。

简言之,一个线性表示n个数据元素的有限序列。

每个数据元素的具体含义在不同的情况下不同,可以是一个整数,一个符号,甚至一页书,甚至是更复杂的信息。

数据元素可以由若干数据项(item)构成。这种情况下把数据元素称为记录。含有大量记录的线性表称为文件

线性表中的数据元素可以是各种各样的,但是同一线性表中的元素必定具有相同的特性,即属于同一种数据对象。相邻数据元素之间存在着序偶关系

线性表中的元素个数n定义为线性表的长度。n=0时称为空表。在非空表中,每个数据元素都有一个确定的位置。i称为数据元素ai在线性表中的位序。

2.2 线性表的顺序表示和实现

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

线性表的第一个存储位置称为线性表的基地址或起始位置

线性表的机内表示:称为线性表的顺序存储结构或顺序映像。

换句话就是,以元素在计算机内“物理位置相邻”来表示线性表中数据元素之间的逻辑关系。

每个数据元素的存储位置都和线性表的起始位置相差一个和数据元素在线性表中的位序成正比的常数。

只要确定了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构

2.3 线性表的链式表示和实现

顺序表的特点:逻辑上相邻的两个元素在物理位置上也相邻。

顺序表得优点:可以随机存取表中任一元素,存储位置可用一个简单的直观的公式来表示。

顺序表的弱点:在做插入或删除操作时,需移动大量元素。

这就要另一种线性表的表示方法:链式存储结构;不要求逻辑上相邻的元素,物理位置上也相邻。所以没有顺序表的弱点,但是也就丧失了顺序表的优点。

2.3.1 线性链表

对于数据元素来说,除了存储其本身的信息外,还要存储其直接后继的信息;

这两部分信息组成了数据元素的存储映像,叫做结点

结点包含两个域:数据域指针域

指针域中存储的信息叫做指针或链

n个结点链结而成一个链表,称为线性表;

用线性链表表示线性表时,数据元素之间的逻辑关系是由结点中的指针指示的。换句话说,指针为数据元素之间的逻辑关系的映像。逻辑上相邻的两个数据元素在物理位置上不要求相邻。这种存储结构被称为非顺序映像或链式映像。(数据元素的物理位置上没有关系)

//定义结点的结构体

typedef struct

{

ElemType data;

struct LNode *next;

}LNode *LinkList;

LinkList是一个头指针;

头结点的指针域指向第一个元素结点的存储位置;

头结点的数据域可以不存储任何信息。

对于链表而言取得第i个元素必须从头指针出发寻找。链表是非随机存取的存储结构。

//从链表中取第i个元素;

Status GetElem_L(LinkList L, int i, ElemType &e)

{

int j;

LinkList p;

p = L->next;

j=1;

while(p&&j<i)

{

p=L->next;

++j;

}

if(!p || j>i)

return ERROR;

e=p->data;

return OK;

}

//链表中插入元素

Status ListInsert_L(LinkList &L, int i, ElemType &e)//头指针,插入位置(i之前),要插入的数据;

{

int j=0;

LinkList p;

p =L;

while(p&&j<i-1) //寻找第i-1个结点

{

p=p->next;

++j;

}

if(!p||j>i-1) return ERROR;

s =(LinkLikst)malloc(sizeof(LNode));

s->data=e;

s->next=p->next;

p->next =s;

return OK;

}

//删除第i个元素

Status ListDelete_L(LinkList &L, int i, ElemType &e)

{

int j=0;

LinkList p q;

p = L;

while(p&&j<i-1)

p=p->next;

++j;

if(!p || j>i-1)

return ERROR;

q=p->next;

p->next=q->next;

e=q->data;

free(q);

}

单链表是一种动态结构,整个可用存储空间可以为多个链表共享。每个链表占用的空间不需要预先分配划定,而是可以根据系统应需求即时生成。

建立链表的过程也就是一个动态生成链表的过程

//建立链表

void CreateList_L(LinkList &L, int n)

{

L = (LinkList)malloc(sizeof(LNode));

L->Next =NULL;

LinkList p;

int i=0;

while(i=n;i>0;--i)

{

p = (LinkList)malloc(sizeof(LNode));

scanf(&p->data);

p->next=L->Next;

L->Next = p;

}

}

//归并两个单链表

void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc,)

{

LinkList pa,pb,pc;

pa = La->Next;

pb = Lb->Next;

Lc = pc = La;  //用La的头结点为Lc的头结点;

while(pa && pb)

{

if(pa->Data<=pb->Data)

{

pc->Next = pa;  //第一次时pc和Lc都指向同一个位置。即a1;更新pc的后继

pc =pa;   //更新pc,pc后移

pa=pa->next;  //pa后移一位

}

else

{

pc->Next=pb; //第一次pc和Lc都指向同一个位置。更新pc的后继;

pc =pb;  //更新pc,pc后移

pb=pb->Next;  //pb后移

}

}

pc->Next = pa ? pa:pb  //插入剩余段

free(Lb)  //释放Lb的头结点;

}

以上算法的空间复杂度比较小,不需要另建新表的结点空间。时间复杂度和顺序表一样。只需要将原来的两个链表的结点之间的关系解除,重新按照元素值非递减关系排列即可。

//静态链表

有一种链表,用数组描述;叫做静态链表

#define MAXSIZE 1000

typedef struct{

ElemType data;

int cur;

}component, SLinkList[MAXSIZE];

这种链表仍然需要预先分配较大的空间,但在作线性表得插入和删除操作时不需要移动元素。每个结点里有个叫cur的变量作为游标代替指针指示结点在数组中的相对位置。整型游标代替了动态指针。当cur为0时,表示链表的结尾;数组的首元素被作为类似链表的头结点。

//静态链表定位元素,在SL中查找第一个值为e的元素

int LocateElem_L(SLinkList S, ElemType e)

{

int i;

i=S[0].cur;

while(i&&S[i].data != e)

{

i=S[i].cur; //相当于p=p->Next

}

return i;

}

//将整个数组空间初始化成一个链表

void InitSpace_SL(SLinkList &space)

{

for(i=0;i<MAXSIZE-1;++i)

space[i].cur=i+1;

space[MAXSIZE-1].cur=0;

}

//从备用空间取得一个结点

int Malloc_SL(SLinkList &space)

{

i=space[0].cur;

if(space[0].cur)

space[0].cur =space[i].cur;

return i;

}

//将空间结点链结到备用链表上

void Free_SL(SLinkList &space, int k)

{

space[k].cur = space[0].cur;

space[0].cur = k;

}

//依次输入集合A和集合B的元素,在一维数组space中建立表示集合(A-B)U(B-A)

//的静态链表,S为其头指针。假设备用空间足够大,space[0].cur为其头指针。

void difference(SLinkList &space,  int &S)

{

InitSpace_SL(space);  //初始化备用空间

S=Malloc_SL(space);  //生成备用空间的头结点

r =S;   //r指向当前备用空间的最后一个结点;

scanf(m,n)   //提供输入A和B的元素个数

for(j=0;j<m;j++)

{

i=Malloc_SL(space);  //从备用链表取得一个结点

scanf(space[i].data);  //用户输入集合A的元素

space[r].cur=i;      //插入到表尾

r=i;  //更新r

}

space[r].cur=0;  //最后一个元素的指针(游标)为空

//至此S中插入了所有集合A的元素;

for(j=0; j<n ;j++)

{

scanf(b);//需要判断b有没有在A中,遍历A即可;

p=S;  //指的是在与集合A的中元素匹配的位置前一个位置,不匹配则为0;初始化

k=space[S].cur;  //记录当前用来与b比较的元素在哪,初始化k=第一个节点

while(k!=space[r].cur&&space[k].data !=b)

{

p=k;

k=space[k].cur;  //k向后移(逻辑后移)

}

if(k==space[r].cur)  //当前表中不存在该元素,则插入到表尾

{

i=Malloc_SL(space);

space[i].cur=space[r].cur;

space[r].cur=i;

space[i].data=b;

}

else  //当前表中已有该元素,删除

{

space[p].cur=space[k].cur;  k

Free_SL(space,k);

if(r==k) r=p;  //如果删除的k是队尾r,需要把更新队尾r,此时p是队尾了(p是k前一个位置)

}

}

}

2.3.2 循环链表

表中最后一个结点的指针域指向头结点;整个链表形成一个环;由此,从表中任一结点出发均可找到表中其他结点。

注意:循环链表的算法中循环条件变成了是否等于头指针。

但是有的链表没有头指针(头结点)。

2.3.3 双向链表

以上的链式存储结构只有一个指示直接后继的指针域。

由此,从某个结点出发只能顺指针往后寻找其他结点。

若要寻找结点的直接前趋,则需从表头指针出发。

换句话说:单链表的NextElem的执行时间为O(1),PriorElem的执行时间为O(n)。

为了克服单链表的这个单向性缺点,可以利用双向链表。

顾名思义,在双向链表中有两个指针域,其一指向直接后继,另一指向直接前趋。

//双向链表存储结构表示

typedef struct DuLNode

{

ElemType       data;

struct DuLNode  *prior;

struct DuLNode  *next;

}DuLNode, *DuLinkList;

//插入结点

Status ListInsert_DuL(DuLinkList &L, int i, ElemType e)//第i个位置之前插入

{

if(!(p=GetElemP_DuL(L,i)))//确定第i个元素额指针p,如果指针不存在,则报错;

return ERROR;

if(!(s=(DuLinkList)malloc(sizeof(DuLNode)))) return ERROR;

s->date=e;

s->prior=p->prior; p->prior->next=s;

s->next=p;p->prior=s;

return OK;

}

//删除结点

Status ListDelete_DuL(DuLinkList &L, int i, ElemType e)

{

if(!(p=GetElemP_DuL(L,i)))

return ERROR;

e=p->data;

p->prior->next=p->next;

p->next->prior=p->prior;

}

链表的优点:

空间的合理利用;插入和删除时不需要移动;

链表的缺点:

求表长不如顺序表;

链表的位序概念淡化,结点之间的关系用指针来表示;

带头结点的线性链表定义:

Typedef struct LNode //结点类型

{

ElemType data;

Struct LNode  *next;

}*Link, *Position;

Typedef struct{  //链表类型

Link  head, tail;  //分别指向线性链表的头结点和最后一个结点;

int   len;       //链表长度;

}LinkList

2.4 一元多项式的表示及相加

原文地址:https://www.cnblogs.com/grooovvve/p/10398409.html

时间: 2024-10-05 05:04:45

数据结构2_线性表的相关文章

自学数据结构——顺序线性表

胡乱写了一些代码 /* ============================================================================ Name : sqlist.c Author :codecup Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ==========================================

软考之路--数据结构之线性表

数据就是数值,也就是我们通过观察.实验或计算得出的结果.数据有很多种,最简单的就是数字.数据也可以是文字.图像.声音等.数据可以用于科学研究.设计.查证等.结构,组成整体的各部分的搭配和安排,两者完美结合在一起,我们这样需要重新认识她,对她重新审视与定义:数据结构是程序设计的重要理论和技术基础,她所讨论的内容和技术,对从事软件项目的开发有重要作用,通过学习数据结构,我们学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所设计的数据悬着适当的逻辑结构.存储结构及其相应的操作方法,为提高应

[笔记]python数据结构之线性表:linkedlist链表,stack栈,queue队列

python数据结构之线性表 python内置了很多高级数据结构,list,dict,tuple,string,set等,在使用的时候十分舒心.但是,如果从一个初学者的角度利用python学习数据结构时,这些高级的数据结构可能给我们以迷惑. 比如,使用list实现queue的时候,入队操作append()时间复杂度可以认为是O(1),但是,出队操作pop(0)的时间复杂度就是O(n). 如果是想利用python学学数据结构的话,我觉得还是自己实现一遍基本的数据结构为好. 1.链表 在这里,我想使

自学数据结构——顺序线性表2

1 /* 2 ============================================================================ 3 Name : sqlist.c 4 Author : codecup 5 Version : 6 Copyright : Your copyright notice 7 Description : Hello World in C, Ansi-style 8 ==================================

数据结构:线性表插入一次删除一次的代码

#include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <stack> #include <queue> #include <cstdio> using namespace std; int insertsqlist(int weizhi,double charu,int *t,double b[]){   

数据结构之线性表(顺序存储结构)

小学生放学都是要按顺序排队的,一个接一个,每个小学生的前后位置是固定的,这样便于迅速清点. 其实这就是一个线性表,从这件事里我们就可以找到很多关于线性表的特性,如 1.线性表是一个序列,它是有顺序的(排队) 2.第一个元素无前驱,最后一个无后继,其他每个元素都有一个前驱和后继(一个接一个) 3.元素是有限的(小学生的个数是有限的) 4.数据类型都相同(都是小学生在排队) 说明白线性表示什么,下面我们直接看线性表的实现 线性表的实现分顺序存储结构和链式存储结构 顺序存储结构: #define LI

数据结构:线性表之单链表

线性表(亦作顺序表)是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的.线性表有两种存储结构: ①顺序存储结构,即存储单元在一段连续的地址上存储,常见的数组就是顺序存储结构的线性表: ②链式存储结构,即存储单元在不连续的地址上存储.因为其不连续性,除了要存数据元素信息(数据域)外,还要存储它后继元素(结点)的地址(指针域,链).学习链式结构最好将结点结构牢记于心,如下图: 链表的每个结点只含有一个指

数据结构之线性表

线性表是最简单最常用的一种数据结构,在生活中各个方面都有应用. 线性表的定义:线性表大多数情况下是除了第一个位置的数据元素只存在后继元素,最后一个位置的数据元素只存在前驱元素外,所有数据元素都存在前驱和后继的一个有限序列.举个简单的例子就是:字母表中除了 a 只存在后继 b,z 只存在前驱 y之外,剩余的所有字母全部都有前驱和后继.为什么是大多数情况下,是因为线性表的链式存储结构中除了单向链表,还有循环链表和双向链表. 线性表的存储结构:顺序存储(数组实现,需要预先分配连续的内存空间)和链式存储

浅谈数据结构之线性表顺序存储(一)

 首先,数据结构是由某一数据元素集合及该集合中所有数据元素之间的关系组成.具体来说,数据结构应当包含三方面的内容:(1).数据的逻辑结构:(2).数据的存储结构:(3).对数据所施加的操作.而数据的存储结构形式有两种:顺序存储与链式存储.在这里,先谈一谈线性表的顺序存储. 线性表:零个或多个数据元素的有限序列.第一,它是一个序列,也就是说,元素之间是有顺序的:第二,它是有限的,即元素个数是有限的.而线性表的顺序存储结构,说白了,就是在内存中找块地,通过占位的形式把一定的内存空间给占了,然后把相同