线性表算法总结

mac2024-05-29  33

目录

定义

分类

优点

特征

基本操作

存储结构

结构特点

线性表的推广

参考资料

顺序表结点定义 

创建顺序表

删除顺序表中所有值为x的元素 

删除顺序表中重复的元素  

将偶数元素放到奇数元素之前 

反转顺序表的元素 

反转顺序表区间[l,h)中的元素

顺序表循环左移K位 

单链表结点定义 

用arr中的元素创建一个长度为n的带头结点的单链表 

删除单链表L中所有值为x的结点 

反转单链表


定义

线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。

在稍复杂的线性表中,一个数据元素可由多个数据项(item)组成,此种情况下常把数据元素称为记录(record),含有大量记录的线性表又称文件(file)。

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

线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…,n时,ai有且仅有一个直接前驱 [1]  。

分类

我们说“线性”和“非线性”,只在逻辑层次上讨论,而不考虑存储层次,所以双向链表和循环链表依旧是线性表。

在数据结构逻辑层次上细分,线性表可分为一般线性表和受限线性表。一般线性表也就是我们通常所说的“线性表”,可以自由的删除或添加结点。受限线性表主要包括栈和队列,受限表示对结点的操作受限制。

优点

线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。

特征

1.集合中必存在唯一的一个“第一元素”。

2.集合中必存在唯一的一个 “最后元素” 。

3.除最后一个元素之外,均有唯一的后继(后件)。

4.除第一个元素之外,均有唯一的前驱(前件)。

基本操作

1)MakeEmpty(L) 这是一个将L变为空表的方法

2)Length(L) 返回表L的长度,即表中元素个数

3)Get(L,i) 这是一个函数,函数值为L中位置i处的元素(1≤i≤n)

4)Prior(L,i) 取i的前驱元素

5)Next(L,i) 取i的后继元素

6)Locate(L,x) 这是一个函数,函数值为元素x在L中的位置

7)Insert(L,i,x)在表L的位置i处插入元素x,将原占据位置i的元素及后面的元素都向后推一个位置

8)Delete(L,p) 从表L中删除位置p处的元素

9)IsEmpty(L) 如果表L为空表(长度为0)则返回true,否则返回false

10)Clear(L)清除所有元素

11)Init(L)同第一个,初始化线性表为空

12)Traverse(L)遍历输出所有元素

13)Find(L,x)查找并返回元素

14)Update(L,x)修改元素

15)Sort(L)对所有元素重新按给定的条件排序

16) strstr(string1,string2)用于字符数组的求string1中出现string2的首地址

存储结构

线性表主要由顺序表示或链式表示。在实际应用中,常以栈、队列、字符串等特殊形式使用。

顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,称为线性表的顺序存储结构或顺序映像(sequential mapping)。它以“物理位置相邻”来表示线性表中数据元素间的逻辑关系,可随机存取表中任一元素。

链式表示指的是用一组任意的存储单元存储线性表中的数据元素,称为线性表的链式存储结构。它的存储单元可以是连续的,也可以是不连续的。在表示数据元素之间的逻辑关系时,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置),这两部分信息组成数据元素的存储映像,称为结点(node)。它包括两个域;存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链 [1]  。

结构特点

1.均匀性:虽然不同数据表的数据元素可以是各种各样的,但对于同一线性表的各数据元素必定具有相同的数据类型和长度。

2.有序性:各数据元素在线性表中的位置只取决于它们的序号,数据元素之前的相对位置是线性的,即存在唯一的“第一个“和“最后一个”的数据元素,除了第一个和最后一个外,其它元素前面均只有一个数据元素(直接前驱)和后面均只有一个数据元素(直接后继)。

线性表的推广

时间有序表、排序表、和频率有序表都可以看做是线性表的推广。如果按照结点到达结构的时间先后,作为确定结点之间关系的,这样一种线性结构称之为时间有序表。例如,在红灯前停下的一长串汽车,最先到达的为首结点,最后到达的为尾结点;在离开时最先到达的汽车将最先离开,最后到达的将最后离开。这些汽车构成了一个队列,实际上就是一个时间有序表。栈和队列都是时间有序表。频率有序表是按照结点的使用频率确定它们之间的相互关系的,而排序表是根据结点的关键字值来加以确定的。 [2]

参考资料

1.  严蔚敏,吴伟民.数据结构(c语言版).北京:清华大学出版社,2011年:18-272.  AdamDrozdek .C++数据结构与算法 :清华大学出版社 ,2014

顺序表结点定义 

#define MaxSize 100 //最大长度 typedef int ElemType; //元素类型 struct SeqList {     ElemType data[MaxSize];     int length; //当前长度 }; 

创建顺序表

SeqList* CreateSeqList(ElemType arr[], int n){ //用arr中的元素创建一个长度为n的顺序表 SeqList *L=(SeqList *)malloc(sizeof(struct SeqList)); L->length=n; for(int i=0; i<n; i++){ L->data[i]=arr[i]; } return L; }

删除顺序表中所有值为x的元素 

void DeleteAllx(SeqList *L, ElemType x){ //删除顺序表中所有值为x的元素 int i=0,j=0; for(; i<L->length; i++){ if(L->data[i]!=x){ L->data[j++]=L->data[i]; } } L->length=j; }

删除顺序表中重复的元素  

void DeleteSame(SeqList &L){ //删除顺序表中重复的元素 int i,j,k; i=j=k=0; for(i=1; i<L.length; i++){ for(k=0; k<=j; k++){ if(L.data[i]==L.data[k]) break;//data[0]~data[j]中有相同元素 } if(k>j) L.data[++j]=L.data[i];//说明data[i]与data[0]~data[j]都不相同 } L.length=j+1; }

将偶数元素放到奇数元素之前 

void PreOdd(SeqList *L){ //将偶数元素放到奇数元素之前 int i=0,j=0; for(; i<L->length; i++){ if(L->data[i]%2==0){//将满足条件的元素前移 ElemType t=L->data[i]; L->data[i]=L->data[j]; L->data[j]=t; j++; } } }

反转顺序表的元素 

void Reverse(SeqList *L){ //反转顺序表的元素 int n=L->length; for(int i=0; i<n/2; i++){ ElemType t=L->data[i]; L->data[i]=L->data[n-i-1]; L->data[n-i-1]=t; } }

反转顺序表区间[l,h)中的元素

void Reverse(SeqList *L,int l,int h){ //反转顺序表区间[l,h)中的元素 for(int i=l, j=h-1; i<j; i++, j--){ ElemType t=L->data[i]; L->data[i]=L->data[j]; L->data[j]=t; } }

顺序表循环左移K位 

void Converse(SeqList *L, int k){ //顺序表循环左移K位 k=k%L->length; Reverse(L,0,L->length); //全部反转 Reverse(L,0,k); //反转前k个元素 Reverse(L,k,L->length); //反转后面length-k个元素 }

单链表结点定义 

typedef int ElemType; struct Node{ ElemType data; Node* next; Node(ElemType d){ data=d; next=NULL; } }; typedef Node * LinkList;

用arr中的元素创建一个长度为n的带头结点的单链表 

LinkList CreateLinkList(ElemType arr[], int n){ //用arr中的元素创建一个长度为n的带头结点的单链表 LinkList L=(LinkList)malloc(sizeof(struct Node)); L->next=NULL; LinkList r=L; for(int i=0; i<n; i++){ LinkList p=(LinkList)malloc(sizeof(struct Node)); p->data=arr[i]; p->next=NULL; r->next=p;//尾插法建表 r=p; } return L; }

删除单链表L中所有值为x的结点 

void DeleteAllx(LinkList L, ElemType x){ //删除单链表L中所有值为x的结点 LinkList p = L; while(p->next!=NULL){ if(p->next->data==x){ LinkList t=p->next; p->next=t->next; free(t); }else{ p=p->next; } } }

反转单链表

void Reverse(LinkList L){ //反转单链表 LinkList p=L->next; //扫描指针 L->next=NULL; //取出头节点 while(p!=NULL){ LinkList q=p->next; //保存p结点的后继结点 p->next=L->next; //用头插法插入L链表 L->next=p; p=q; //后移 } }

 

 

 

 

 

 

 

最新回复(0)