K:线性表的实现—链表
单链表的概念:
采用链式存储方式存储的线性表称之为链表,链表中每个节点包含存放数据元素的值的数据域和存放指向逻辑上相邻节点的指针域。若一个节点中只包含一个指针域,则称此链表为单链表。
单链表的特点:
1. 单链表是通过指向后继节点的指针把它的一串节点连接成一个链
2. 以线性表这种第一个数据元素的存储地址作为线性表的起始地址,称做线性表的头指针。一个单链表就是由他的头指针head来唯一的标识他。
3. 单链表中的最后一个节点(尾节点)没有后继,所以它的指针域的值用空指针null。
4. 为了操作方便,在第一个存入数据的节点之前加入一个虚节点称为“头节点”,头结点的数据域一般不存放具体的值,指针域存放指向第一个节点(首节点)的指针,指向头节点的指针为单链表的头指针。
5. 若线性表为空表,则头指针的指针域为空
单链表的节点类的相关代码(java):
class Node<T>
{
public T data;//用于存储相关的数据域
public Node<T> next;//用于存储相关的指针域
public Node()
{
this(null,null);
}
public Node(T data)
{
this(data,null);
}
public Node(T data,Node next)
{
this.data=data;
this.next=next;
}
}
单链表实现的相关代码(java):
public class LinkedList<T> implements List<T>
{
public Node head;//用于存储头指针
public LinkedList()
{
head=new Node();
}
public void clear()//清空,时间复杂度为O(1)
{
head=new Node();
}
public boolean isEmpty()//判空操作,时间复杂度为O(1)
{
return head.next==null;
}
public int length()//求长度
{
int k=0;
Node p=head.next;
while(p!=null)
{
k++;
p=p.next;
}
return k;
}
public T get(int i)throws Exception//按位查找,其时间复杂度为O(n)
{
int j=0;
Node p=head.next;
while(j<i&&p!=null)
{
j++;
p=p.next;
}
if(j>i||p==null)
{
throw new Exception(“查找的位置不存在”);
}
return p.data;
}
public int indexOf(T x)//按值查找,其时间复杂度为O(n)
{
int j=0;
Node p=head.next;
while(p!=null&&!p.data.equals(x))
{
j++;
p=p.next;
}
if(p==null)
return -1;
else
return j;
}
public void insert(int i,T x)throws Exception//插入操作,其时间复杂度为O(n)
{
int j=-1;
Node p=head;
while(j<i-1&&p!=null)//用于找到插入位置的前一个节点
{
j++;
p=p.next;
}
if(i-1<j||p==null)
{
throw new Exception(“插入的位置不合法”);
}
Node s=new Node(x);
s.next=p.next;
p.next=s;
}
public void remove(int i)throws Exception//删除操作,时间复杂度为O(n)
{
int j=-1;
Node p=head;
while(j<i-1&&p.next!=null)
{
j++;
p=p.next;
}
if(j>i-1||p.next!=null)
{
throw new Exception(“删除的位置不合法”);
}
p.next=p.next.next;
}
}
ps:对于单链表的删除操作而言,其必须要找到进行删除的节点的前继节点,之后才能进行删除。删除某个特定节点的另一个思路是,将下一个节点的数据域的值赋值给本节点的数据域,之后,删除通过该特定节点,去删除下一个节点。这样做的局限在于,无法删除单链表中的最后一个节点。
其它链表:
除了单链表之外,还有单链表的改进和结构的调整,常见的有循环链表和双向链表以及双向循环链表。
ps:对于“链表”该名词,有两种含义,一种是指单链表,一种是指各种形式的链式存储结构。为此,“链表”的具体含义应该取决于上下文。
单向循环链表:
循环链表也称为环形链表,其结构和单链表相似,只是将单链表的首尾相连,即将单链表的最后一个节点的后继指针指向第一个节点,从而构成一个环形链表
在循环链表中,每一个节点都有后继,所以,从循环链表的任意一个节点出发都可以访问到单链表中的所有节点。
对于单链表和循环链表,其API的实现上大多数没有什么区别,仅有的区别在于判断是否为最后一个节点的时候是否为头结点,而不是单链表实现上的最后一个节点为null。
在实现循环链表时,既可以用头指针来标识循环链表,也可以用尾指针(所谓的尾指针,指的是指向末尾节点的指针)来标识,也可以头尾指针都用。若仅用头指针标识循环链表,则访问第一个节点的时间复杂度为O(1),但是访问最后一个节点的时间复杂度为O(n);若仅用尾指针标识的循环链表,则不论是访问第一个节点还是访问最后一个节点,其时间复杂度为O(1),所以,在实际操作中,使用尾指针来标识循环链表,这样会简化某些操作
双向链表
在单链表中的节点仅仅包含指向其后继节点的指针,所以要查找一个指定节点的后继节点,只要顺着其后继指针即可找到,其时间复杂度为O(1),但是,若其要找到某个指定节点的前驱节点,则其需要从单链表的表头开始顺着链依次进行查找,其时间复杂度为O(n),为了解决这个问题,让每一个节点都有两个指针域,一个指向前驱节点,一个指向后继节点,此种链表就称为双向链表。
双向循环链表
将双向链表的首尾进行相连即可构成双向循环链表
双向链表的节点插入及删除操作图
插入:
删除:
K:线性表的实现—链表的更多相关文章
- 玩转C线性表和单向链表之Linux双向链表优化
前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...
- c/c++ 线性表之单向链表
c/c++ 线性表之单向链表 线性表之单向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点是NULL. 真实的第一个节点是头节点,头节点不存放数据, ...
- 线性表之单链表C++实现
线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...
- [数据结构 - 第3章] 线性表之单链表(C++实现)
一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...
- [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)
[数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构) C#中的链表(源码) 可空类 ...
- 【Java】 大话数据结构(2) 线性表之单链表
本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...
- 续上文----线性表之单链表(C实现)
本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...
- 线性表 (单链表、循环链表-python实现)
一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...
- 数组线性表ArrayList 和链表类LinkedList
数组线性表类ArrayList 和链表类LinkedList 是实现List接口的两个具体类.ArrayList 数组储存元素,这个数组是动态创建的.如果元素个数超过了数组的容量,就创建一个更大的新数 ...
随机推荐
- PHP大文件分割上传(分片上传)
服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关 upload_max_filesize = 2M //PHP最大能接受的文件大小 post_max_size = 8M //PHP能收 ...
- struts2 谷歌浏览器保存date类型数据时报错
一同事发现一个bug,在chrome上保存一个表单时,后台会报错,而在firefox上则可以正常保存. 奇怪的地方在于,后端的程序是同一个,而在浏览器上查看请求header时,两个浏览器对应的字段内容 ...
- SQL Server学习之路(八):扩展SQL语句
0.目录 1.问题描述 2.第一种方法 通过GROUP BY子句解决 3.第二种方法 通过聚合函数解决 4.第三种方法 在select...from...中的from后面嵌套一个表 5.第四种方法 在 ...
- SQL Server学习之路(五):“增删改查”之“改”
0.目录 1.前言 2.通过SSMS修改数据 3.通过SQL语句修改数据 3.1 修改单列数据 3.2 修改多列数据 1.前言 增删改查都是对数据的操作,其中"改"对应的SQL语句 ...
- SQL Server学习之路(三):“增删改查”之“增”
0.目录 1.前言 2.通过SSMS添加数据 3.通过SQL语句添加数据 3.1 添加单条数据 3.2 添加多条数据 4.通过其他表导入数据 4.1 通过数据库中的其他表导入数据 4.2 通过exce ...
- MySQL安装(yum、二进制、源码)
MySQL安装(yum.二进制.源码) 目录 1.1 yum安装... 2 1.2 二进制安装-mysql-5.7.17. 3 1.2.1 准备工作... 3 1.2.2 解压.移动.授权... 3 ...
- js 深拷贝和浅拷贝
js 深拷贝和浅拷贝 先举一下项目中遇到的两个例子: 例子1: var json = $.parseJSON(data.data);//data.data是接口返回的值var a = json.cha ...
- 查看SQL Server数据读写分离,并设置读写分离
1. 查看读写分离脚本,直接执行以下脚本: select name,is_read_committed_snapshot_on from sys.databases 执行结果列表中,name表示数据库 ...
- Zookeeper 集群安装
负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据[均匀]分摊到多个操作单元上执行,负载均衡的关键在于[均匀].常见互联网分布式架构如上,分为客户端 ...
- Git 二分调试法,火速定位疑难Bug!
你一定遇到过,一个很久没修改过的功能,莫名其妙的出现了问题?肉眼查代码.屡逻辑完全找不到问题点?前两天还好好的功能,怎么这个今天就不行了?这两天改动了这么多代码,到底是那一次改动引发的 Bug? 这样 ...