这个寒假有点长呀~~~~之前学数据结构与算法时,用C语言实现,现在开始学Java了,就决定用Java重新学习一下,学以致用呀!
每天一点点,积少成多!-_-
学习视频网址:Java数据结构与算法视频教程
单链表
一、链表的特点
- 链表是有序的列表,以节点的方式来存储;
- 每个节点包含data域,next域:指向下一个节点;
- 链表的各个节点不一定是连续存储
二、实例:水浒英雄排行榜管理
1. 要求
使用带head头的单向链表实现–水浒英雄排行榜管理。
- 完成对英雄人物的增删改查操作;
- 第一种方法在添加英雄时,直接添加到链表的尾部;
- 第二种方法在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示).
2 代码实现
2.1 创建英雄节点HeroNode
//定义HeroNode,每个HeroNode对象就是一个节点
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;
}
//为了显示方便,重写toString方法
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
2.2 定义SingleLinkList,管理英雄
这个类里面实现各种操作(方法)
class SingleLinkList{
//先初始化一个头节点,头节点不要动,不存放具体数据
private HeroNode head = new HeroNode(0,"","");
//add(); 添加(不考虑编号顺序)
//list(); 显示链表(遍历)
//addByOrder(); 按照编号顺序添加
//update(); 修改节点的信息
//del(); 删除节点的信息
.
}
2.2.1 添加节点到单向链表
【备注:不考虑编号顺序】
/**
* 1.找到当前链表的最后一个节点
* 2.将最后这个节点的next指向新的节点
*
*/
public void add(HeroNode heroNode){
//因为head节点不能动,因此我们需要找一个辅助遍历节点
HeroNode temp = head;
while (true){
if (temp.next == null){
break;
}
temp = temp.next;
}
//退出while循环时,temp指向了链表的最后
//将这个节点的next指向新的节点
temp.next = heroNode;
}
2.2.2 显示链表【遍历】
public void list(){
if (head.next == null){
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
while(true){
if (temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
2.2.3 按照编号的顺序添加
思路如下:
- 找到新添加的节点p的位置,通过辅助变量;
- 新的节点p.next = temp.next;
- temp.next = p;
public void addByOrder(HeroNode heroNode){
//注意:temp位于添加位置的前一个节点
HeroNode temp = head;
boolean flag = false; //flag标志添加的编号是否存在,默认为false
while(true){
if (temp.next == null){
break;
}
if (temp.next.no > heroNode.no){ //位置找到,就在temp的后面插入
break;
}else if (temp.next.no == heroNode.no){ //说明希望添加的heroNode编号已经存在
flag = true; //编号已存在
break;
}
temp = temp.next;
}
//判断flag的值
if(flag){ //不能添加,编号已经存在
System.out.printf("准备插入的英雄的编号%d已经存在了,不能加入\n",heroNode.no);
}else{
//插入到链表中,temp后面
heroNode.next = temp.next;
temp.next = heroNode;
}
}
2.2.4 修改节点的信息
【备:根据no编号来修改,即不修改no,修改姓名name或者绰号nickname】
//根据newHeroNode的no来修改
public void update(HeroNode newHeroNode){
//判断是否为空
if (head.next == null){
System.out.println("链表为空");
return;
}
//根据no编号,找到需要修改的节点
HeroNode temp = head.next;
boolean flag = false; //表示是否找到该节点
while(true){
if (temp == null){ //已经遍历完链表
break;
}
if (temp.no == newHeroNode.no){
flag = true; //找到
break;
}
temp = temp.next;
}
//根据flag,判断是否找到要修改的节点
if (flag){
temp.name = newHeroNode.name;
temp.nickname = newHeroNode.nickname;
}else{
System.out.printf("没有找到编号为%d的节点,不能修改\n",newHeroNode.no);
}
}
2.2.5 删除节点的信息
从单链表中删除一个节点:
- 先找到需要删除的这个节点的前一个节点temp;
- temp.next = temp.next.next;
- 被删除的节点,将不会有其它引用指向,会被垃圾回收机制回收。
【备:比较时,是temp.next.no 和待删除节点的no进行比较】
//删除节点
public void del(int no){
HeroNode temp = head;
boolean flag = false;//标志是否找到待删除节点
while(true){
if (temp == null){ //已经遍历完链表
break;
}
if (temp.next.no == no){
flag = true; //找到
break;
}
temp = temp.next;
}
//判断flag
if (flag){
temp.next = temp.next.next;
}else{
System.out.printf("待删除的%d节点不存在\n",no);
}
}
三、单链表的简单应用
1. 单链表中节点的个数
【备:如果是带头结点的链表,不统计头节点。】
public static int getLength(HeroNode head){
if (head.next == null){//空链表
return 0;
}
int length = 0;
HeroNode cur = head.next;
while(cur != null){
length++;
cur = cur.next;
}
return length;
}
2. 单链表的反转
思路:【头插法】
//反转链表
public static void reverseList(HeroNode head){
//如果当前链表为空,无需反转
if ( head.next == null){
return;
}
HeroNode cur = head.next;
HeroNode next = null;//指向当前节点cur的下一个节点
head.next = null;
while(cur != null){
next = cur.next; //暂时保存
cur.next = head.next;
head.next = cur;
cur = next;
}
}
3. 合并两个有序的单链表,合并之后的链表依然有序
public static HeroNode MergeOrderedList(HeroNode herohead1,HeroNode herohead2){
HeroNode cur1 = herohead1.next;
HeroNode cur2 = herohead2.next;
HeroNode temp1,temp2;
HeroNode result = new HeroNode(0,"","");
HeroNode tail = result;
result.next = null;
while(cur1 != null && cur2 != null){
if (cur1.no <= cur2.no){
temp1 = cur1.next;
tail.next = cur1;
cur1 = temp1;
tail = tail.next;
}else{
temp2 = cur2.next;
tail.next = cur2;
cur2 = temp2;
tail = tail.next;
}
}
//其中一个链表不为空
while (cur1 != null){
tail.next = cur1;
tail = tail.next;
cur1 = cur1.next;
}
while (cur2 != null){
tail.next = cur2;
tail = tail.next;
cur2 = cur2.next;
}
return result;
}