介绍
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
链表是有序的列表,但是它在内存中的存储如下
小结上图:
- 链表是以节点的方式来存储,是链式存储。
- 每个节点包含data域,next域:指向下一个节点。
- 如图:发现链表的各个节点不一定是连续存储。
- 链表分为带头节点的链表和没有带头节点的链表,根据实际需求来确定。
案例
使用带头节点的单项链表实现-水浒英雄排行榜管理
- 完成英雄人物的增删改查操作。
- 第一种方法在添加时,直接添加在链表的尾部。
- 第二种方式在添加时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
- 修改
- 先找到改节点,通过遍历
- temp.name = newHerNode.name;
temp.nickName = newHerNode.nickName;
- 删除
代码实现
package com.xiong.com.xiong.linkedList;
/*
* @创建人:_╃君戰ヽ天
* @创建时间:2019-10-25 11:22
* @描述:单链表
*/
public class SingleLinkedList {
public static void main(String[] args) {
//先创建几个节点
HerNode herNode1 = new HerNode(1,"宋江","及时雨");
HerNode herNode2 = new HerNode(2,"卢俊义","玉麒麟");
HerNode herNode3 = new HerNode(3,"吴用","智多星");
HerNode herNode4 = new HerNode(4,"林冲","豹子头");
//创建要给链表
linkedList linkedList = new linkedList();
//加入 第一种方式
/* linkedList.add(herNode1);
linkedList.add(herNode3);
linkedList.add(herNode2);
linkedList.add(herNode4);*/
//加入 第二种方式
linkedList.addByNo(herNode1);
linkedList.addByNo(herNode3);
linkedList.addByNo(herNode2);
linkedList.addByNo(herNode4);
//修改
// linkedList.update(new HerNode(5,"小卢","麒麟"));
//显示
linkedList.list();
linkedList.delete(5);
//显示
linkedList.list();
}
}
//定义 linkedList 用来管理我们的英雄
class linkedList {
//定义头节点 数据为空
private HerNode head = new HerNode(0,"","");
//添加节点 第一种方法在添加时,直接添加在链表的尾部。
public void add(HerNode herNode){
HerNode temp = head;
while (true){
//得到链表的最后
if(temp.next == null){
break;
}
//获取为空的链表
temp = temp.next;
}
//得到为空的链表 赋值添加
temp.next = herNode;
}
//第二种方式在添加时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
public void addByNo(HerNode herNode){
HerNode temp = head;
boolean flag = false; //希望添加的是否存在
while (true){
if(temp.next == null){ //说明链表已经到最后
break;
}
if(temp.next.no > herNode.no){ //位置找到,就在temp后面添加即可
break;
}else if(temp.next.no == herNode.no){ //说明希望添加的已经存在
flag = true;
break;
}
//如果上面三个都不成立 则后移在判断
temp = temp.next;
}
if(flag){
System.out.println("准备插入的英雄:"+herNode.nickName+herNode.name+",已经存在");
}else{
herNode.next = temp.next;
temp.next = herNode;
}
}
//修改
public void update(HerNode newHerNode){
HerNode temp = head.next;
boolean flag = false; //是否位置找到
while (true){
if(temp == null){ //说明链表已经到最后
break;
}
if(temp.no == newHerNode.no){ //位置找到
flag = true;
break;
}
//如果上面都不成立 则后移在判断
temp = temp.next;
}
if(flag){ //找到修改
temp.name = newHerNode.name;
temp.nickName = newHerNode.nickName;
System.out.println("修改完成:");
}else{ //没有找到则提示
System.out.println("需要修改的英雄:"+newHerNode.nickName+newHerNode.name+"不能修改,因为他不存在");
}
}
//删除
public void delete(int no){
HerNode temp = head;
boolean flag = false; //是否位置找到
while (true){
if(temp.next == null){ //说明链表已经到最后
break;
}
if(temp.next.no == no){ //位置找到
flag = true;
break;
}
//如果上面都不成立 则后移在判断
temp = temp.next;
}
if(flag){ //找到 删除
temp.next = temp.next.next;
System.out.println("删除成功");
}else{ //没有找到则提示
System.out.println("需要删除的no为:"+no+"的节点,不存在无法删除");
}
}
//显示链表
public void list(){
//判断是否链表为空
if(head.next == null){
System.out.println("链表为空");
return;
}
//头节点不能动 获取下一个节点
HerNode temp = head.next;
while (true){
//判断链表是否到最后
if(temp == null){
break;
}
//输出
System.out.println(temp);
//temp后移 *
temp = temp.next;
}
}
}
//定义HerNode,每一个HerNode对象就是一个节点
class HerNode{
public int no; //编号
public String name; //姓名
public String nickName; //外号
public HerNode next; //指向下一个节点
public HerNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HerNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}