单链表
链表介绍
链表是有序的列表,但是它在内存中的存储如下:
- 链表是以节点的方式来存储,是链式存储
- 每个节点包含data域,next域:指向下一个节点
- 如图:发现链表的各个节点不一定是连续存储
- 链表分带头结点的链表和没有头结点的链表,根据实际需求来确定
单链表(带头结点)逻辑结构示意图如下
单链表的应用实例
使用带head头的单向链表实现 - 水浒英雄排行榜管理完成对英雄任务的增删改查
- 第一种方法在添加英雄时,直接添加到链表的尾部 (需要一个辅助指针遍历到链表尾部[因为头结点不能动],进行添加)
- 第二种方式在添加英雄的时候,根据排名将英雄插入到指定位置(如果有这个排名则添加失败,并给出提示)
- 修改节点功能
- 通过遍历,找到该节点
- 对节点数据进行修改
- 删除节点
代码
public class singleLinkedList {
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
/**
* 测试单链表尾部插入
*
*/
@Test
public void testAdd() {
SingleLinkedList singleLinked = new SingleLinkedList();
singleLinked.add(hero1);
singleLinked.add(hero3);
singleLinked.add(hero2);
singleLinked.add(hero4);
singleLinked.list();
}
//序号插入
@Test
public void testAddByOrder(){
SingleLinkedList singleLinked = new SingleLinkedList();
singleLinked.addByOrder(hero2);
singleLinked.addByOrder(hero1);
singleLinked.addByOrder(hero4);
singleLinked.addByOrder(hero3);
singleLinked.list();
}
@Test
public void testUpdate(){
SingleLinkedList singleLinked = new SingleLinkedList();
singleLinked.addByOrder(hero2);
singleLinked.addByOrder(hero1);
singleLinked.addByOrder(hero4);
singleLinked.addByOrder(hero3);
System.out.println("修改前---------------------");
singleLinked.list();
HeroNode hero5 = new HeroNode(4, "林冲!!!", "豹子头$$$$$$$$");
singleLinked.update(hero5);
System.out.println("修改后---------------------");
singleLinked.list();
}
@Test
public void testDelete(){
SingleLinkedList singleLinked = new SingleLinkedList();
singleLinked.addByOrder(hero2);
singleLinked.addByOrder(hero1);
singleLinked.addByOrder(hero4);
singleLinked.addByOrder(hero3);
System.out.println("删除前----------------------------");
singleLinked.list();
singleLinked.delete(4);
System.out.println("删除后----------------------------");
singleLinked.list();
}
}
class SingleLinkedList {
//先创建一个头结点
HeroNode head = new HeroNode(0, "", "");
//直接在链表尾部添加元素
public void add(HeroNode heroNode) {
//由于头结点不能动,所以需要定义一个节点,指向头结点
HeroNode tmp = head;
while (true) {
if (tmp.next == null) {
break;
}
tmp = tmp.next;
}
tmp.next = heroNode;
}
// 按照顺序插入
public void addByOrder(HeroNode heroNode){
HeroNode tmp = head;
while (true){
if (tmp.next == null){
break;
}
if (tmp.next.no == heroNode.no){
System.out.printf("顺序为%d的节点已经存在\n",heroNode.no);
return;
}else if (tmp.next.no > heroNode.no){
break;
}
tmp = tmp.next;
}
//插入
heroNode.next = tmp.next;
tmp.next = heroNode;
}
//链表节点修改 ,只能修改存在的节点,且不能修改节点的no
public void update(HeroNode heroNode){
if (head.next == null){
System.out.println("链表为空!!");
return;
}
HeroNode tmp = head.next;
boolean flag = false;
while (true){
if (tmp == null){
break;
}
if (tmp.no == heroNode.no){
flag = true;
break;
}
tmp = tmp.next;
}
if (flag){
tmp.name = heroNode.name;
tmp.nickName = heroNode.nickName;
}else {
System.out.printf("链表中不存在序号为%d的节点\n",heroNode.no);
}
}
//删除链表元素,根据序号进行删除
public void delete(int no){
if (head.next == null){
System.out.println("链表为空!!");
return;
}
HeroNode tmp = head;
boolean flag = false;
while (true){
if (tmp.next == null){
break;
}
if (tmp.next.no == no){
flag = true;
break;
}
tmp = tmp.next;
}
if (flag){
tmp.next = tmp.next.next;
}else {
System.out.printf("链表中没有序号为%d的节点\n",no);
}
}
//显示链表
public void list() {
if (head.next == null) {
System.out.println("链表为空!!");
return;
}
HeroNode tmp = head.next;
while (true) {
if (tmp == null) {
break;
}
System.out.println(tmp);
tmp = tmp.next;
}
}
}
class HeroNode {
public int no;
public String name;
public String nickName;
public HeroNode next;
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}