链表(Linked List): 单链表

Posted jianyingjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表(Linked List): 单链表相关的知识,希望对你有一定的参考价值。

链表(Linked List)介绍

链表是有序的列表,但是它在内存中是存储如下:

技术图片

 小结:

  1. 链表是以节点的方式来存储,是链式存储。
  2. 每个节点包含 data域 , next域 : 指向下一个节点。
  3. 如图:发现链表的各个节点不一定是连续存储。
  4. 链表分带头节点的链表 和 没有带头节点的链表,根据实际的需求来确定。

单链表介绍

单链表(带头节点)逻辑结构示意图如下:

技术图片

  •  单链表的应用实例

使用带head头的单向链表实现—水浒英雄排行榜管理完成对英雄人物的增删改查操作。

1)第一种方法在添加英雄时,直接添加到链表的尾部

思路分析示意图:

技术图片

2)第二种方法在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)

思路分析示意图:

技术图片

3)修改节点的功能

思路:

①先找到该节点,通过遍历 

②temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname;

4)删除节点

思路分析示意图:

技术图片

5)完整代码实现

技术图片
  1 package com.jyj.linkedList;
  2 
  3 public class SingleLinkedListDemo {
  4     public static void main(String[] args) {
  5         //测试
  6         //先创建节点
  7         HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
  8         HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
  9         HeroNode hero3 = new HeroNode(3,"吴用","智多星");
 10         HeroNode hero4 = new HeroNode(4,"林冲","豹子头");
 11         
 12         //创建链表
 13         SingleLinkedList singleLinkedList = new SingleLinkedList();
 14         //加入
 15 //        singleLinkedList.add(hero1);
 16 //        singleLinkedList.add(hero4);
 17 //        singleLinkedList.add(hero2);
 18 //        singleLinkedList.add(hero3);
 19         
 20         //加入
 21         singleLinkedList.addByOrder(hero1);
 22         singleLinkedList.addByOrder(hero4);
 23         singleLinkedList.addByOrder(hero2);
 24         singleLinkedList.addByOrder(hero3);
 25         
 26         //显示
 27         singleLinkedList.list();
 28         
 29         singleLinkedList.update(new HeroNode(2,"小卢","玉麒麟~~~"));
 30         
 31         System.out.println("修正后:");
 32         //显示
 33         singleLinkedList.list();
 34         
 35         singleLinkedList.del(1);
 36         singleLinkedList.del(4);
 37         System.out.println("删除后:");
 38         //显示
 39         singleLinkedList.list();
 40         
 41     }
 42 }
 43 
 44 //定义SingleLinkedList 管理英雄
 45 class SingleLinkedList {
 46     //先初始化一个头节点,头节点不要动,不存放具体的数据
 47     private HeroNode head = new HeroNode(0,"","");
 48     
 49     //添加节点到单向链表
 50     //思路:当不考虑编号的顺序时
 51     //1.找到当前链表的最后节点
 52     //2.将最后这个节点的next 指向  新的节点
 53     public void add(HeroNode heroNode) {
 54         //因为head节点不能动,因此我们需要一个辅助节点 temp
 55         HeroNode temp = head;
 56         //遍历链表,找到最后
 57         while(true) {
 58             //找到链表的最后
 59             if(temp.next == null) {
 60                 break;
 61             }
 62             //如果没有找到最后,就将temp后移
 63             temp = temp.next;
 64         }
 65         //当退出while循环时,temp就指向了链表的最后
 66         //将最后这个节点的next 指向 新的节点
 67         temp.next = heroNode;
 68     }
 69     
 70     //添加英雄时,根据排名将英雄插入到指定位置
 71     //(如果有这个排名,则添加失败,并给出提示)
 72     public void addByOrder(HeroNode heroNode) {
 73         //因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助我们找到添加的位置,
 74         //因为单链表,我们找到的temp是位于 添加位置的第一个节点,否则插入不了
 75         HeroNode temp = head;
 76         boolean flag = false; //flag标志添加的编号是否存在,默认为false
 77         while(true) {
 78             if(temp.next == null) { //说明temp已经在链表的最后
 79                 break;
 80             }
 81             if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入
 82                 break;
 83             }else if(temp.next.no == heroNode.no) { //说明将要添加的heroNode的编号已经存在
 84                 flag = true; //说明编号存在
 85                 break;
 86             }
 87             //后移,遍历当前链表
 88             temp = temp.next;
 89         }
 90         
 91         if(flag) {
 92             System.out.printf("编号 %d 已经存在,不能再添加~
",heroNode.no);
 93         }else {
 94             //插入到链表中,temp的后面
 95             heroNode.next = temp.next;
 96             temp.next = heroNode;
 97         }
 98     }
 99     
100     //修改节点的信息,根据no编号来修改,即no编号不能改
101     public void update(HeroNode newHeroNode) {
102         //判空
103         if(head.next == null) {
104             System.out.println("链表为空");
105             return;
106         }
107         //找到需要修改的节点,根据no编号
108         //定义一个辅助变量
109         HeroNode temp = head.next;
110         boolean flag = false; //表示是否找到该节点
111         while(true) {
112             if(temp == null) {
113                 break; //已经遍历完链表
114             }
115             if(temp.no == newHeroNode.no) {
116                 //找到
117                 flag = true;
118                 break;
119             }
120             temp = temp.next;
121         }
122         //根据flag 判断是否找到要修改的节点
123         if(flag) {
124             temp.name = newHeroNode.name;
125             temp.nickname = newHeroNode.nickname;
126         }else { //没有找到
127             System.out.printf("编号 %d 不存在,不能修改~",newHeroNode.no);
128         }
129     }
130     
131     //删除链表
132     //思路
133     //1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点
134     //2.说明我们在比较时,是 temp.next.no 和 需要删除的节点的no 比较
135     public void del(int no) {
136         //辅助链表
137         HeroNode temp = head;
138         boolean flag = false; //标志是否找到待删除的节点
139         
140         while(true) {
141             if(temp.next == null) { //已经到链表最后
142                 break;
143             }
144             if(temp.next.no == no) {
145                 //找到待删除节点的前一个节点temp
146                 flag = true;
147                 break;
148             }
149             temp = temp.next; //后移
150         }
151         
152         if(flag) {
153             //删除节点
154             temp.next = temp.next.next;
155         }else {
156             System.out.printf("要删除的 %d 节点不存在
",no);
157         }
158     }
159     
160     //显示链表[遍历]
161     public void list(){
162         //判断链表是否为空
163         if(head.next == null) {
164             System.out.println("链表为空");
165             return;
166         }
167         //因为头节点不能动,因此需要辅助变量来遍历
168         HeroNode temp = head.next;
169         while(true) {
170             //判断是否到链表最后:注意是temp == null,不是temp.next == null
171             if(temp == null) {
172                 break;
173             }
174             //输出节点的信息
175             System.out.println(temp);
176             //将temp 后移,不然就是死循环
177             temp = temp.next;
178         }
179     }
180 }
181 
182 //定义HeroNode,每个HeroNode 对象就是一个节点
183 class HeroNode {
184     public int no;
185     public String name;
186     public String nickname;
187     public HeroNode next; //指向下一个节点
188     
189     //构造器
190     public HeroNode(int no,String name,String nickname) {
191         this.no = no;
192         this.name = name;
193         this.nickname = nickname;
194     }
195 
196     //为了显示方便,重写toString
197     @Override
198     public String toString() {
199         return "HeroNode [no=" + no + ", name=" + name + ", nickname="
200                 + nickname + "]";
201     }
202 }
View Code

以上

以上是关于链表(Linked List): 单链表的主要内容,如果未能解决你的问题,请参考以下文章

leetcode链表--5linked-list-cycle(单链表是否有环)

leetcode链表--6linked-list-cycle-ii(有环单链表环的入口结点)

382 Linked List Random Node 链表随机节点

链表 (Linked List)

异或链表(XOR Linked List)

C 单链表