第二章 线性表【数据结构与算法】1

简介: 第二章 线性表【数据结构与算法】1

配套资源下载

数据结构资源下载导航【数据结构】

第二章 线性表

2.1 应用实例

应用实例一 约瑟夫环问题(Josephus problem)

约瑟夫环问题是由古罗马的史学家约瑟夫提出的。问题描述为:编号为1,2.,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将其密码作为新的m值,并从其顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。这个游戏的实现只需将每个人的信息什 为一个结点,结点中存放每个人的编号和密码。由于要反复做删除操作,所以采用单向循环链表实现比较方便,详见本章2.6节。

应用实例二 一元多项式运算器

要实现一元多项式运算器,首先要设计表示一元多项式P=p0+p1x+p2x^2+…+pn x^n"的合适的 数据结构,并支持多项式的下列运算。

  • 建立多项式。
  • 输出多项式。
  • +,两个多项式相加,建立并输出和多项式。
  • -,两个多项式相减,建立并输出差多项式。
  • *,多项式乘法。
  • (),求多项式的值。
  • derivative(),求多项式导数。

这个问题看起来很复张,但只要用本章将要学习的带头结点的单链表来存储多项式,头结点中存放多项式的参数(如项数等),问题就可以迎刃而解。详细的实现分析及算法见本章2.6节。

2.2 线性表的概念及运算

2.2.1线性表的逻辑结构

线性表是n(n>=0)个数据元素的有限序列。在表中,元素存在线性的逻辑关系:表中有且仅有一个开始结点;有且仅有一个终端结点;除开始结点外,表中的每个结点均只有一个前驱结点(predecessor);除终端结点外,表中的每个结点均只有一个后继结点(successor)。根据它们之间的关系可以排成一个线性序列,记作(a1,a2,…,an)

2.2.2 线性表的运算

基本操作

① InitList(L)       线性表初始化,构造一个空的线性表L。
② ListLength(L)     求线性表的长度,返回线性表L中数据元素的个数 
③ GetElem(L,i,x)    用x返回线性表中的第i个数据元素的值。
④ locaionElem(L,x)    按值查找,确定数据元素x在表中的位置。  
⑤ ListInsert(L,i,x)   插入操作,在线性表L中第i个位置之前插入一个新元素。L的长度加1。
⑥ ListDelete(L,i)   删除操作,删除线性表L中的第i个元素,L的长度减1。  
⑦ ListEmpty(L)      判断线性表L是否为空,空表返回TRUE,非空表返回FALSE。  
⑧ ClearList(L)      将已知的线性表L置为空表。
⑨ DestroyList(L)      销毁线性表L。

其他操作:合并、分拆、复制、排序等等。

2.3 线性表的顺序存储

2.3.1 顺序表

顺序存储是指在内存中用一块地址连续的存储空间按顺序存储线性表的各个数据元素。采用顺序存储结构 的线性表称为“顺序表”顺序表中逻辑上相邻的数据元素在物理存储位置上也是相邻的。

#define MAXSIZE <线性表可能达到的最大长度>  
typedef int ElemType;
typedef struct
{   ElemType elem[MAXSIZE];
  int length;//线性表长度
} SeqList;

2.3.2 顺序表的基本运算

相关代码请看配套资源

1-顺序表.c

int main(){
  SeqList _L;
  SeqList *L=&_L;
  //初始化 
  Init(&_L);
  //创建 
  CreateList(L,4);
  Output(L);
  //插入 
  printf("在1处插入1\n"); 
  Insert(L,1,1);
  printf("在2处插入2\n"); 
  Insert(L,2,2);
  printf("插入之后"); 
  Output(L);
  printf("表长:%d\n",ListLength(L));
  //删除
  printf("删除1\n"); 
  ElemType d=-1;
  Delete(L,1,&d);
  printf("删除之后"); 
  Output(L);
  //查询
  printf("查询1\n"); 
  ElemType x=1;
  int i=Location(L,x);
  printf("序号%d\n",i);
  printf("按索引i查询\n"); 
  ElemType y;
  GetElem(L,i,&y);
  printf("值%d",y); 
} 

运行结果如下



[例 2-1] 两个顺序表合并

有两个顺序表LA和LB,其元素均为非递减有序排列, 编写一个算法,将它们合并成一个顺序表LC,要求LC也是非递减有序排列。
算法思路:依次扫描A和B的元素,比较当前元素的值,将较小值的元素赋给C,如此直到一个线性表扫描完毕,然后将未外理完的顺序表的余下部分元麦连在表C的后面即可。表C的容量要能够容纳A、B两个线性表中的所有元素。

[算法2-5] 两个顺序表合并

void merge(SeqList* A, SeqList* B,SeqList* C)
{ int i,j,k;
  i=1;j=1;k=1;
  while (i<=A->length && j<= B->length)
    if (A->elem[i]<=B->elem[j])
      C->elem[k++]=A->elem[i++];
    else C->elem[k++]=B->elem[j++];
  while (i<=A->length)
    C->elem[k++]=A->elem[i++];
  while (j<=B->length)
    C->elem[k++]=B->elem[j++];
  C->length=A->length+B->length;
}

算法的时间复杂度是0(m+n),其中m是A的表长,n是B的表长。

2.4 线性表的链式存储

链式存储,通过“链”建立起数据元素之间的逻辑关系,这种用链接方式存储的线性表简称链表(link list)。

2.4.1 单链表

链表中的每一个结点都至少包括两个与,一个域存储数据元素信息,称为“数据域”;另一个域存储之间后继元素的地址,称为“指针域”。

结点定义如下:

typedef struct code 
{ DataType data;//数据域
  struct node * next;//指针域
}LNode,*LinkList;

n个元素的线性表通过每个结点的指针域连 接成了一条“链子”,故形象地称之为“链表”。因为每个结点中只有一个指向其直接后继的指针所以称其为单链表

2.4.2 单链表基本运算

相关代码请看配套资源

2-单链表.c

void main(){
  //建立 
  LinkList h=CreatByBear();
  OutPut(h);
  //插入 
  printf("在1处插入1\n"); 
  Insert(h,1,1);
  printf("在2处插入2\n"); 
  Insert(h,2,2); 
  printf("插入之后\n"); 
  OutPut(h);
  //删除 
  printf("删除2\n"); 
  Delete(h,2);
  printf("删除之后\n"); 
  OutPut(h);
  //按序号查询 
  LNode *p;
  p=Get(h,1);
  printf("按序号查找到的信息如下:\n");
  printf("%d\n",p->data);
  //按值查询
  LNode *s;
  s=Locate(h,1);
  printf("按值查找到的信息如下:\n");
  printf("%d\n",s->data);
} 

运行结果如下



[例]

有两个单链表LA和LB,其元素均为非递减有序排列, 编写一个算法,将它们合并成一个单链表LC,要求LC也是非递减有序排列。

要求:新表LC利用原表的存储空间。

[解]

LinkList MergeLinkList(LinkList LA,LinkList LB)
{
  LNode *pa,*pb;
  LinkList LC;
  pa=LA->next;
  pb=LB->next
  LC=LA;
  LC->next=NULL;
  r=LC;
  while(pa&&pb)
  {  
    if(pa->data<=pb->data)
    { 
      r->next=pa;
      r=pa;
      pa=pa->next;  
    }
    else
    {  
      r->next=pb;
      r=pb;
      pb=pb->next; 
    }
  if(pa) r->next=pa;
  else  r->next=pb;
  free(LB);
  return(LC);
}
相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
5月前
|
存储 算法 数据安全/隐私保护
第二章 线性表【数据结构与算法】【精致版】
第二章 线性表【数据结构与算法】【精致版】
85 0
|
8月前
|
算法
数据结构与算法2.1线性表、链表
数据结构与算法2.1线性表、链表
29 0
数据结构与算法2.1线性表、链表
|
5月前
|
人工智能 算法 C语言
【408数据结构与算法】—线性表的定义和分析(二)
【408数据结构与算法】—线性表的定义和分析(二)
|
9月前
|
存储 算法
第二章 线性表【数据结构与算法】3
第二章 线性表【数据结构与算法】3
28 0
|
9月前
|
存储 算法
第二章 线性表【数据结构与算法】2
第二章 线性表【数据结构与算法】2
38 0
|
12月前
|
存储 算法 Java
数据结构与算法(二):线性表
上一篇《数据结构与算法(一):概述》中介绍了数据结构的一些基本概念,并分别举例说明了算法的时间复杂度和空间复杂度的求解方法。这一篇主要介绍线性表。
65 0
|
存储 算法
数据结构/数据结构与算法实验一 线性表的相关算法实现
数据结构/数据结构与算法实验一 线性表的相关算法实现
65 0
数据结构/数据结构与算法实验一 线性表的相关算法实现
|
机器学习/深度学习 人工智能 算法
【408数据结构与算法】—线性表的定义和分析(二)
线性表的定义:线性表示具有相同数据类型的n(n>=0)个数据元素的有限序列,其中n为表长,当n=0 时,线性表是一个空表,若用L命名线性表,则一般表示为:L=(a1,a2,……,ai,an)
【408数据结构与算法】—线性表的定义和分析(二)
|
存储 算法 小程序
educoder数据结构与算法 线性表 第2关:实现一个链接存储的线性表
educoder数据结构与算法 线性表 第2关:实现一个链接存储的线性表
323 0
educoder数据结构与算法 线性表 第2关:实现一个链接存储的线性表
|
存储 算法
educoder数据结构与算法 线性表 第1关:实现一个顺序存储的线性表
educoder数据结构与算法 线性表 第1关:实现一个顺序存储的线性表
413 0
educoder数据结构与算法 线性表 第1关:实现一个顺序存储的线性表