单链表的概念:

 采用链式存储方式存储的线性表称之为链表,链表中每个节点包含存放数据元素的值的数据域和存放指向逻辑上相邻节点的指针域。若一个节点中只包含一个指针域,则称此链表为单链表。

单链表的特点:

 1. 单链表是通过指向后继节点的指针把它的一串节点连接成一个链

 2. 以线性表这种第一个数据元素的存储地址作为线性表的起始地址,称做线性表的头指针。一个单链表就是由他的头指针head来唯一的标识他。

 3. 单链表中的最后一个节点(尾节点)没有后继,所以它的指针域的值用空指针null。

 4. 为了操作方便,在第一个存入数据的节点之前加入一个虚节点称为“头节点”,头结点的数据域一般不存放具体的值,指针域存放指向第一个节点(首节点)的指针,指向头节点的指针为单链表的头指针。

 5. 若线性表为空表,则头指针的指针域为空

单链表的节点类的相关代码(java):

  1. class Node<T>
  2. {
  3. public T data;//用于存储相关的数据域
  4. public Node<T> next;//用于存储相关的指针域
  5. public Node()
  6. {
  7. this(null,null);
  8. }
  9. public Node(T data)
  10. {
  11. this(data,null);
  12. }
  13. public Node(T data,Node next)
  14. {
  15. this.data=data;
  16. this.next=next;
  17. }
  18. }

单链表实现的相关代码(java):

  1. public class LinkedList<T> implements List<T>
  2. {
  3. public Node head;//用于存储头指针
  4. public LinkedList()
  5. {
  6. head=new Node();
  7. }
  8. public void clear()//清空,时间复杂度为O(1)
  9. {
  10. head=new Node();
  11. }
  12. public boolean isEmpty()//判空操作,时间复杂度为O(1)
  13. {
  14. return head.next==null;
  15. }
  16. public int length()//求长度
  17. {
  18. int k=0;
  19. Node p=head.next;
  20. while(p!=null)
  21. {
  22. k++;
  23. p=p.next;
  24. }
  25. return k;
  26. }
  27. public T get(int i)throws Exception//按位查找,其时间复杂度为O(n)
  28. {
  29. int j=0;
  30. Node p=head.next;
  31. while(j<i&&p!=null)
  32. {
  33. j++;
  34. p=p.next;
  35. }
  36. if(j>i||p==null)
  37. {
  38. throw new Exception(“查找的位置不存在”);
  39. }
  40. return p.data;
  41. }
  42. public int indexOf(T x)//按值查找,其时间复杂度为O(n)
  43. {
  44. int j=0;
  45. Node p=head.next;
  46. while(p!=null&&!p.data.equals(x))
  47. {
  48. j++;
  49. p=p.next;
  50. }
  51. if(p==null)
  52. return -1;
  53. else
  54. return j;
  55. }
  56. public void insert(int i,T x)throws Exception//插入操作,其时间复杂度为O(n)
  57. {
  58. int j=-1;
  59. Node p=head;
  60. while(j<i-1&&p!=null)//用于找到插入位置的前一个节点
  61. {
  62. j++;
  63. p=p.next;
  64. }
  65. if(i-1<j||p==null)
  66. {
  67. throw new Exception(“插入的位置不合法”);
  68. }
  69. Node s=new Node(x);
  70. s.next=p.next;
  71. p.next=s;
  72. }
  73. public void remove(int i)throws Exception//删除操作,时间复杂度为O(n)
  74. {
  75. int j=-1;
  76. Node p=head;
  77. while(j<i-1&&p.next!=null)
  78. {
  79. j++;
  80. p=p.next;
  81. }
  82. if(j>i-1||p.next!=null)
  83. {
  84. throw new Exception(“删除的位置不合法”);
  85. }
  86. p.next=p.next.next;
  87. }
  88. }

ps:对于单链表的删除操作而言,其必须要找到进行删除的节点的前继节点,之后才能进行删除。删除某个特定节点的另一个思路是,将下一个节点的数据域的值赋值给本节点的数据域,之后,删除通过该特定节点,去删除下一个节点。这样做的局限在于,无法删除单链表中的最后一个节点。

其它链表:

 除了单链表之外,还有单链表的改进和结构的调整,常见的有循环链表和双向链表以及双向循环链表。

 ps:对于“链表”该名词,有两种含义,一种是指单链表,一种是指各种形式的链式存储结构。为此,“链表”的具体含义应该取决于上下文。

单向循环链表:

 循环链表也称为环形链表,其结构和单链表相似,只是将单链表的首尾相连,即将单链表的最后一个节点的后继指针指向第一个节点,从而构成一个环形链表

在循环链表中,每一个节点都有后继,所以,从循环链表的任意一个节点出发都可以访问到单链表中的所有节点。

 对于单链表和循环链表,其API的实现上大多数没有什么区别,仅有的区别在于判断是否为最后一个节点的时候是否为头结点,而不是单链表实现上的最后一个节点为null。

 在实现循环链表时,既可以用头指针来标识循环链表,也可以用尾指针(所谓的尾指针,指的是指向末尾节点的指针)来标识,也可以头尾指针都用。若仅用头指针标识循环链表,则访问第一个节点的时间复杂度为O(1),但是访问最后一个节点的时间复杂度为O(n);若仅用尾指针标识的循环链表,则不论是访问第一个节点还是访问最后一个节点,其时间复杂度为O(1),所以,在实际操作中,使用尾指针来标识循环链表,这样会简化某些操作

双向链表

 在单链表中的节点仅仅包含指向其后继节点的指针,所以要查找一个指定节点的后继节点,只要顺着其后继指针即可找到,其时间复杂度为O(1),但是,若其要找到某个指定节点的前驱节点,则其需要从单链表的表头开始顺着链依次进行查找,其时间复杂度为O(n),为了解决这个问题,让每一个节点都有两个指针域,一个指向前驱节点,一个指向后继节点,此种链表就称为双向链表。

双向循环链表

 将双向链表的首尾进行相连即可构成双向循环链表

双向链表的节点插入及删除操作图

插入:



删除:

回到目录|·(工)·)

K:线性表的实现—链表的更多相关文章

  1. 玩转C线性表和单向链表之Linux双向链表优化

    前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...

  2. c/c++ 线性表之单向链表

    c/c++ 线性表之单向链表 线性表之单向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点是NULL. 真实的第一个节点是头节点,头节点不存放数据, ...

  3. 线性表之单链表C++实现

    线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...

  4. [数据结构 - 第3章] 线性表之单链表(C++实现)

    一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...

  5. [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)

    [数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构)    C#中的链表(源码)    可空类 ...

  6. 【Java】 大话数据结构(2) 线性表之单链表

    本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...

  7. 续上文----线性表之单链表(C实现)

    本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...

  8. 线性表 (单链表、循环链表-python实现)

    一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...

  9. 数组线性表ArrayList 和链表类LinkedList

    数组线性表类ArrayList 和链表类LinkedList 是实现List接口的两个具体类.ArrayList 数组储存元素,这个数组是动态创建的.如果元素个数超过了数组的容量,就创建一个更大的新数 ...

随机推荐

  1. Postgresql中的explain

    PostgreSQL为每个收到的查询设计一个查询规划.选择正确的匹配查询结构和数据属性的规划对执行效率是至关重要要的,所以系统包含一个复杂的规划器来试图选择好的规划.你可以使用EXPLAIN命令查看查 ...

  2. 【JDK1.8】JDK1.8集合源码阅读——IdentityHashMap

    一.前言 今天我们来看一下本次集合源码阅读里的最后一个Map--IdentityHashMap.这个Map之所以放在最后是因为它用到的情况最少,也相较于其他的map来说比较特殊.就笔者来说,到目前为止 ...

  3. Win10系统下的Tomcat7.0配置

    为什么不用更高版本的Tomcat呢?好几个老师都说7.0的版本最好用,所以就推荐用这个.安Tomcat之前,我电脑上装的是jdk 9,安装了好几次Apache都不能启动,日志显示的是"启动报 ...

  4. MySQL系列:基于binlog的增量订阅与消费(一)

    在一些业务场景中,像在数据分析中我们有时候需要捕获数据变化(CDC):在数据审计中,我们也往往需要知道数据从这个点到另一个点的变化:同样在实时分析中,我们有时候需要看到某个值得实时变化等. 要解决以上 ...

  5. linux crontab yum安装

    crontab工具来做计划任务,定时任务,执行某个脚本等等 1.检查是否已安装crontab # crontab -bash: crontab: command not found 执行 cronta ...

  6. 使用Dagger2做静态注入, 对比Guice.

    Dagger 依赖注入的诉求, 这边就不重复描述了, 在上文Spring以及Guice的IOC文档中都有提及, 既然有了Guice, Google为啥还要搞个Dagger2出来重复造轮子呢? 因为使用 ...

  7. 【微服务】之六:轻松搞定SpringCloud微服务-API网关zuul

    通过前面几篇文章的介绍,我们可以轻松搭建起来微服务体系中比较重要的几个基础构建服务.那么,在本篇博文中,我们重点讲解一下,如何将所有微服务的API同意对外暴露,这个就设计API网关的概念. 本系列教程 ...

  8. [Contiki系列论文之1]Contiki——为微传感器网络而生的轻量级的、灵活的操作系统

    说明:本系列文章翻译自Contiki之父Adam Dunkels经典论文,版权归原作者全部. Contiki是由Adam Dunkels及其团队开发的系统,研读其论文是对深入理解Contiki系统的最 ...

  9. Spark Shuffle模块——Suffle Read过程分析

    在阅读本文之前.请先阅读Spark Sort Based Shuffle内存分析 Spark Shuffle Read调用栈例如以下: 1. org.apache.spark.rdd.Shuffled ...

  10. 数据库中的參照完整性(Foreign Key)

    之前在项目中遇到了这样一个问题,我举得简单的样例来说明. 比方我们有两个表,一个表(department)存放的是部门的信息,比如部门id,部门名称等:还有一个表是员工表(staff),员工表里面肯定 ...