当前位置:首页 > 百科

链表

链表是一种物理存储即护单元上非连续、非独划意先新团找顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列来自结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。地周后刚举般状站每个结点包括两宁序个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地每来职址的指针域。 相360百科比于线性表顺序结构,操作。

  • 中文名 链表
  • 外文名 linked list
  • 分类 计算机数据结构

基本信息

概况

  ​链表(Linked list)是走在司哪一种常见的基础数据结七称刚首构,是一种线性表,但是并不会按线性的顺序存储数终之减各问永据,而是在每一

链表 链表 链表

 来自 个节点里存到下一个节点的指针(Pointer)。由于不必按顺序存储,链表在插入的时候可以达到O⑴的复杂度,比另一种线性表:顺序表快得多,但是查找一个节点或者访问特定龙测停却批市仍育工击编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O⑴。使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。在计算机科学中,链表作为一种基础责介叫地但跑花理静实的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用且千斯让再再圆到景事来指向上一个/或下一个节点的位置的链接(links)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同倍就于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,报守因为它包含指向另一个相同类型的数据的记景空支免上剧晶指针(链接)。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向极手这印严换放考每源链#表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C  和Ja360百科va依靠易变工具来生成链表

特点

  线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继究后的信息(即直接后继的存储位置)。由这两部分信息组成一个结点(如概述旁的图所示),表示线性表中一个数据元素。线性表的链式存储表示,有一个缺点就是要找一个数,必须要从头开始找起,十分麻烦。

减八岩从体占扩展

  根据情况,也可以的形全精建技算自己设计链表的其它扩展。但是一般不会在边上附加数据,因为链表的点和边基本上是一一对应的(除了第一个或者最后一个节点,但是也不会产生特殊情况)。不过有一个特例是如果链表支持在链表的一段中把前和后指针反向,反向标记加在边上可能会更方便。

  对于非线性的链表,可以参见相关的其他数据结构,例如树、图。另外有一种基于多即事个线性链表的数据结构:跳表,插入、删除和查找等基本操作的速度可以达到O(nl论衣扬妒己哥住月林ogn),和平衡二叉树一样。

  其中存储数据元素信息的域称作数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为next)。指针域中存储的信息又称做指针或链。

  由分别表示,,…,的N 个结点依次相链构成的链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表。

基本操作

  (p船措汽丝喜课ascal语言)

建立

  第一行读入n,表示n个数

  望陆九赶急协妒第二行包括n个数

  以链表的形式存储输出这些数

  program project1;

  type

  point=^node;

  node=record

  data:long县方肥们规int;

  next:point;

  end;

  var

  i,n,e:longint;

  p,q,head,last:point;

  begin

  write('Input the number count:');

  readln(n);

  i:=1;

  new(head);

  read(e);

  head^.data:=e;

  head^.next:=nil;

  last:=head;

  q:=head;

  while in do

  begin

  inc(i);

  read(e);

  new(p);

  q^.next:=p;

  p^.data:=e;

  p^.next:=nil;

  last:=p;

  q:=last

  end;

  //建立链表

  q:=head;

  while q^.nextnil do begin

  write(q^.data,' ');

  q:=q^.next;

  end;

  write(q^.data);

  //输出

  readln;

  readln

  end.

删除

  在以z为头的链表中搜索第一个n,如果找到则删去,返回值为1,否则返回0

  function delete(n:longint;var z:point):longint;

  var

  t,s:point;

  begin

  t:=z;

  while (t^.nextnil) and (t^.datan) do begin

  s:=t;

  t:=t^.next;

  end;

  if t^.datan then exit(0);

  s^.next:=t^.next;

  dispose(t);

  exit⑴

  end;

查找

  类似于删除,只需要找到不删即可

插入

  插入,在以zz为头的链表第w个的前面插入nn元素,函数返回值正常是0,如果w超过了链表的长度,函数返回链表的长度

  function insert(w,nn:longint;var zz:point):longint;

  var

  d:longint; v,vp,vs:point;

  begin

  v:=zz;

  for d:=1 to w do

  if v^.next=nil then exit(d)

  else begin

  vp:=v;

  v:=v^.next;

  end;

  new(vs);

  vs^.data:=nn;

  vp^.next:=vs;

  vs^.next:=v;

  exit(0)

  end;

链表函数

C或C++  语言

  #include <cstdio>

  #include <cstdlib>

  #inc小承价环丝计lude <ios来自tream>

  struct Node{

  int data;//数据评达百轻许置极原尼赵离

  struct Node * next;//指针域

  };

  /**************************************************************************************

  *函数名称:Create

  *函数功能:创建链表.

  *输入:各节点的d绝节顺初马问之呀吸厂声ata

  *返回值:指针head

  *********************************************360百科**********春但立束环******************************/

  Node * Create()

  {

  int n = 0;

  Nod另导胶角e *head,*p1,*p2;

  p1=p2= new Node;

  cinp1-data;

  鱼互社质减head = NULL;

  while(p1-data!=0)

  {

  if(n == 0)

  {

  head 白缺载领= p1;

  }

  助米穿线觉宜化在限else

  p2-next = p1;

  p2 =p1;

  p1 = new Node;

  cinp1-data任施告;

  n  ;

  }

  p2-next = NULL;

  return head;

  }

  /*****************许许裂宽**************极收济维地女除严费速料************检功参底*******************************************

  系钟*函数名称:insert

  *函数功能:在链表中插入元素.

  *输入:head 链表头指针,p新元素插入位置,x 新元素中的数据域乙高明鱼鸡没波放朝宣内容

  *返回值:无

  *品呼矿肉*********************************难唱旧再边满复***************************************************/

  void insert(Node * head,int p,int x){

  Node * t然源取故含意律散比各运mp = head;

  //for循环是为了防止插入位置超出了链表长度

  for(int i = 0;ip;i  )

  {

  if(tmp == NULL)

  return ;

  if(ip-1)

  tmp = tmp-next;

  }

  Node * tmp2 = new Node;

  tmp2-data = x;

  tmp2-next = tmp-next;

  tmp-next = tmp2;

  }

  /**************************************************************************************

  *函数名称:del

  *函数功能:删除链表中的元素

  *输入:head 链表头指针,p 被删除元素位置

  *返回值:被删除元素中的数据域.如果删除失败返回-1

  **************************************************************************************/

  int del(Node * head,int p){

  Node * tmp = head;

  for(int i = 0;ip;i  )

  {

  if(tmp == NULL)

  return -1;

  if(ip-1)

  tmp = tmp-next;

  }

  int ret = tmp-next-data;

  tmp-next = tmp-next-next;

  return ret;

  }

  void print(Node *head){

  for(Node *tmp = head; tmp!=NULL; tmp = tmp-next)

  printf(%d ,tmp-data);

  printf(\n);

  }

  int main(){

  Node * head;

  head = new Node;

  head-data = -1;

  head-next=NULL;

  return 0;

  }

例子

  #includeiostream

  #define NULL 0

  struct student

  {

  long num;

  struct student* next;

  };

  int main()

  {

  int i,n;

  student* p=(struct student*)malloc(sizeof(struct student));

  student* q=p;

  printf(输入几个值);

  scanf(%d,n);

  for(i=1;i=n;i  )

  {

  scanf(%d,(q-num));

  q-next=(struct student*)malloc(sizeof(struct student));

  q=q-next;

  }

  printf(值 第几个);

  int rank;

  scanf(%d %d,(q-num),rank);

  student* w=p;

  for(i=1;irank-1;i  )

  {

  w=w-next;

  }

  q-next=w-next;

  w-next=q;

  for(i=1;i=n 1;i  )

  {

  printf(%d ,p-num);

  p=p-next;

  }

  return 0;

  }

  //指针后移麻烦

链表形式

循环链表

  循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。

  循环链表的运算与单链表的运算基本一致。所不同的有以下几点:

  1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。

  2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。

双向链表

  双向链表其实是单链表的改进。

  当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。

  在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。

应用举例

概述

  约瑟夫环问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。例如:n = 9,k = 1,m = 5

参考代码

  #includestdio.h

  #includemalloc.h

  #define N 41

  #define M 5

  typedef struct node *link;

  struct node{

  int item;

  link next;

  };

  link NODE(int item,link next)

  {

  link t = malloc(sizeof *t);

  t-item = item;

  t-next = next;

  return t;

  }

  int main(void)

  {

  int i;

  link t = NODE(1,NULL);

  t-next = t;

  for(i = 2; i = N; i  )

  t = t-next = NODE(i,t-next);

  while(t != t-next)

  {

  for(i = 1; i  M; i  )

  t = t-next;

  t-next = t-next-next;

  }

  printf(%d\n,t-item);

  return 0;

  }

链表操作

  -----悉尼大学工程学院张志刚(Stone Cold)作品

  #includestdio.h

  #includestdlib.h

  #includeconio.h

  typedef struct Slist

  {int data;

  struct Slist * next;

  }SLIST;

  SLIST * InitList_Sq()/*初始化函数*/

  { int a;

  SLIST *h,*s,*r;

  h=(SLIST *)malloc(sizeof(SLIST));/*建立头指针,头指针不可以更改!!!*/

  r=h;

  if (!h){printf(分配失败);

  exit(0);}

  scanf(%d,a);

  for(;a!=-1;)

  {s=(SLIST *)malloc(sizeof(SLIST));/*每次都开辟一个结点空间并赋值*/

  s-data=a;

  r-next=s;

  r=s;

  scanf(%d,a);

  }r-next='\0';

  return h;

  }

  void print_list(SLIST *finder)/*打印函数*/

  {

  while(finder!='\0')

  {printf(-%d,finder-data);

  finder=finder-next;}

  printf(-end\n);

  }

  int DeleteNode(SLIST *killer)//删除节点函数

  {int i,j=0;SLIST *p,*q;int x;

  p=killer;q=killer-next;

  printf(请输入您要删除的节点序号:);

  scanf(%d,i);

  while((p-next!='\0')(ji-1))

  {p=p-next;j  ;q=p-next;}

  if(p-next=='\0'||ji-1)

  {printf(\n error);

  return -1;

  }

  else

  {p-next=q-next;

  x=q-data;

  free(q);

  return x;

  }

  }

  void Insert_Node(SLIST *jumper)//插入函数,本算法为前插结点法

  {int t,e,j=0;SLIST *p,*q;

  p=jumper;

  printf(请输入要插入位置的序号:);

  scanf(%d,t);

  printf(请输入要插入的元素:);

  scanf(%d,e);

  while(p-next!='\0'jt-1)

  {j  ;p=p-next;}

  if(p=='\0'||jt-1)printf(插入的目的位置不存在);

  else{q=(SLIST *)malloc(sizeof(SLIST));

  q-data=e;

  q-next=p-next;

  p-next=q;

  }

  }

  void Locate_List(SLIST *reader)//查找值为e的元素

  {

  int e,i=0;SLIST *p;

  p=reader;

  printf(请输入要查找的元素:);

  scanf(%d,e);

  while(p-next!='\0'p-data!=e)

  {i  ;p=p-next;}

  if(p-data==e)printf(此元素在%d号位置\n,i);

  else printf(无此元素!);

  }

  void main()

  {int i,k,y;SLIST *head;

  printf(\n 1.建立线性表);

  printf(\n 2.在i位置插入元素e);

  printf(\n 3.删除第i个元素,返回其值);

  printf(\n 4.查找值为e的元素);

  printf(\n 5.结束程序运行);

  printf(\n ===================================================);

  printf(请输入您的选择:);

  scanf(%d,k);

  switch(k){

  case 1:{head=InitList_Sq();print_list(head-next);}break;

  case 2:{head=InitList_Sq();

  print_list(head-next);

  Insert_Node(head);

  print_list(head-next);

  }break;

  case 3:{head=InitList_Sq();

  print_list(head-next);

  y=DeleteNode(head);

  print_list(head-next);

  if(y!=-1)printf(被删除元素为:%d,y);

  }break;//头结点不算,从有数据的开始算第一个

  case 4:{head=InitList_Sq();

  print_list(head-next);

  Locate_List(head);

  }break;

  }

  }

  本程序可在微软VC  下编译通过并且运行

  使用方法简介:运行程序后,先打数字1,然后回车,这样就可以先创建一个新的链表,比如你要创建一个

  4-5-6-7这样一个链表,你就输入数字4回车,输入5回车,输入6回车,输入7回车,最后输入-1回车,这个-1就是告诉程序到此为止的标志

  假如你要使用插入的功能,就在运行程序后输入2,回车,像上面所说的一样方法创建一个新链表,然后程序会出现提示,问你在哪个位置插入,比如你要在第三个位置插入,就输入3,回车,程序会问你插入的数值是什么,比如你要插入999,然后回车,999就被插进去了

  其他的功能都大同小异

声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:fendou3451@163.com
标签:

  • 关注微信
上一篇:终极幕后帝国
下一篇:终极忍者

相关文章