链表(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 已经存在,不能再添加~\n",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 节点不存在\n",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 }

以上

原文地址:https://www.cnblogs.com/jianyingjie/p/12070518.html

时间: 2024-10-08 14:40:59

链表(Linked List): 单链表的相关文章

数据结构实验之链表五:单链表的拆分

数据结构实验之链表五:单链表的拆分 Time Limit: 1000MS Memory limit: 65536K 题目描述 输入N个整数顺序建立一个单链表,将该单链表拆分成两个子链表,第一个子链表存放了所有的偶数,第二个子链表存放了所有的奇数.两个子链表中数据的相对次序与原链表一致. 输入 第一行输入整数N;: 第二行依次输入N个整数. 输出 第一行分别输出偶数链表与奇数链表的元素个数: 第二行依次输出偶数子链表的所有数据: 第三行依次输出奇数子链表的所有数据. 示例输入 10 1 3 22

静态单链表和动态单链表的区别

链表中结点的分配和回收是由系统提供的标准函数malloc和free动态实现的,称之为动态链表. 如果程序支持指针,则可按照我们的一般形式实现链表, 需要时分配,不需要时回收即可. 动态链表的空间是可以动态扩展的. typedef struct  node{ EleType data; struct node * pNext; }Node; 有些高级语言中没有"指针"数据类型,只能用数组来模拟线性链表的结构, 数组元素中的指针"域"存放的不是元素在内存中的真实地址,而

链表1-单链表

链表也是一种线性表,但与线性表不同的是,链表的物理存储结构是一堆地址任意的存储单元.也就是说,链表的数据在内存中的物理位置可能相互邻接,也有可能不邻接. 单链表的基本操作如下: 1 //链表的基本操作 2 //定义结点类 3 template <typename Type> class Node{ 4 public: 5 Type data; 6 Node<Type> *next; 7 Node(const Type &_data){ 8 data=_data; 9 nex

C语言:【单链表】查找单链表的中间节点,要求只能遍历一次

#include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int DataType; typedef struct SListNode {     DataType data;     struct SListNode* next; }SListNode; SListNode* BuyNode(DataType x) {     SListNode* next = (SListNode*)malloc

数据结构与算法之PHP实现链表类(单链表/双链表/循环链表)

链表是由一组节点组成的集合.每个节点都使用一个对象的引用指向它的后继.指向另一个节点的引用叫做链. 链表分为单链表.双链表.循环链表. 一.单链表 插入:链表中插入一个节点的效率很高.向链表中插入一个节点,需要修改它前面的节点(前驱),使其指向新加入的节点,而新加入的节点则指向原来前驱指向的节点(见下图). 由上图可知,B.C之间插入D,三者之间的关系为 current为插入节点的前驱节点 current->next = new              // B节点指向新节点D new->n

链表之循环单链表(用C语言描述)

上回说到建立链表的三种形式,分别是头插法,尾插法,和尾插法MAX?? ??下面讲一下循环单链表?? 循环单链表,字面意思,就是单链表循环了起来,尾节点在输入结束后不会指向NULL,而是指向了头节点head 酱紫,链表就循环了起来 下面是代码实现 #include <stdio.h> #include <stdlib.h> typedef char datatype; typedef struct node { datatype data; struct node *next; in

【链表】实现单链表的逆序

1 public class Main { 2 3 // 就地逆序法 4 public Node reverse(Node head) { 5 // no need to reverse 6 if (head == null || head.next == null || head.next.next == null) { 7 return head; 8 } 9 10 // pointer 11 Node pre = head; 12 Node cur = head.next; 13 Node

待字闺中之单链表和之恋

题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 原题:两个单链表(singly linked list),每一个节点里面一个0-9的数字,输入就相当于两个大数了.然后返回这两个数的和(一个新list).这两个输入的list长度相等. 要求是:不用递归:要求算法在最好的情况下,只遍历两个list一次 ,最差的情况下两遍 分析:如果链表表示的数是从低到高位表示的,则很简单:如果是从高到低,问题就复杂了,进位是万恶之源. 两个单链表,每个节点存储一个0-9的数字

Python与数据结构[0] -&gt; 链表[0] -&gt; 单链表与带表头单链表的 Python 实现

单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利用Python来完成单链表的实现. 1 单链表 不带表头的单链表通常形式如下, node_1 -> node_2 -> node_3 -> node_4 完整代码 1 class Node: 2 def __init__(self, val=None, nxt=None): 3 self.v

【数据结构】单链表&amp;&amp;静态链表详解和代码实例

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构.它动态的为节点分配存储单元.当有节点插入时,系统动态的为结点分配空间.在结点删除时,应该及时释放相应的存储单元,以防止内存泄露.由于是链式存储,所以操作单链表时,必须知道头结点或者头指针的位置.并且,在查找第i个节点时,必须找到第i-1个节点. 1.2 单链表的存储结构代码描述 对于链式存储,通过上一节的讲解相信大家已