题一:获取单链表节点的个数
思路
在HeroNode类中写一个方法public static int getLength(HeroNode head)获取节点个数。如果是带头节点就不统计头节点。
如果head节点的next为null就返回0.否则定义一个length变量用于计数,定义一个辅助变量current,current=head.next,然后循环中只要current不为null就把length加1,再把current后移。循环结束后返回的length就是节点的个数。
方法代码:
//获取单链表的节点个数,如果是带头节点的链表就不统计头节点
public static int getLength(HeroNode head) {
if (head.next == null) {
//为空链表则直接返回0
return 0;
}
int length = 0;//统计有效节点个数
//辅助变量用于遍历
HeroNode current = head.next;
while (current != null) {
length++;
current = current.next;
}
return length;
}
由于SingleLinkedList中头节点是私有的,所以要获取头节点还需要在SingleLinkedList类中写一个方法获取头节点。
//先初始化头节点,不存放具体数据
private HeroNode head = new HeroNode(0, "", "");
//返回头节点
public HeroNode getHead() {
return head;
}
在main方法中
System.out.println("节点个数:" + getLength(singleLinkedList1.getHead()));
运行结果:
题二:查找单链表的倒数第k个节点
思路
编写一个方法,接收head节点,同时接收index(倒数第index个节点)。先把链表从头到尾遍历,得到链表总长Length。得到Length后,从链表第一个节点开始遍历Length-index个节点。比如总共3个节点,要查倒数第一个节点就从第一个节点开始遍历2个节点。使已经知道要遍历几个节点就用for循环,找到了就返回该节点,找不到就返回null。
方法代码
//获取单链表倒数第K个节点
public static HeroNode findLastIndexNode(HeroNode head,int index){
//判断链表是否为空
if(head.next==null){
return null;
}
//先遍历得到节点个数
int Length=getLength(head);
//再遍历到size-index
if(index<=0||index>Length){
return null;//不合适的index就返回null
}
//定义辅助变量temp
HeroNode temp=head.next;
for(int i=0;i<Length-index;i++){
temp=temp.next;
}
return temp;
}
在main方法中
HeroNode res=findLastIndexNode(singleLinkedList1.getHead(),1);
System.out.println("倒数第1个节点为:"+res);
运行结果:
完整代码:
package com.xjj.linkedlist;
public class LinkedList {
public static void main(String[] args) {
//创建节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
//将节点加入链表
singleLinkedList.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
singleLinkedList.add(hero4);
//显示链表
singleLinkedList.list();
System.out.println("按编号顺序插入");
SingleLinkedList singleLinkedList1 = new SingleLinkedList();
//将节点插入链表
singleLinkedList1.addByOrder(hero1);
singleLinkedList1.addByOrder(hero4);
singleLinkedList1.addByOrder(hero2);
singleLinkedList1.addByOrder(hero3);
singleLinkedList1.list();
//测试修改节点
System.out.println("修改节点");
HeroNode newHeroNode = new HeroNode(2, "卢", "玉麒麟--");
singleLinkedList1.update(newHeroNode);
singleLinkedList1.list();
//测试删除节点
System.out.println("删除节点1");
singleLinkedList1.delete(1);//删除第一个节点
singleLinkedList1.list();
System.out.println("删除节点4");
singleLinkedList1.delete(4);//删除第四个节点
singleLinkedList1.list();
// System.out.println("删完");
// singleLinkedList1.delete(2);//删除第二个节点
// singleLinkedList1.delete(3);//删除第三个节点
// singleLinkedList1.list();
System.out.println("节点个数:" + getLength(singleLinkedList1.getHead()));
HeroNode res=findLastIndexNode(singleLinkedList1.getHead(),1);
System.out.println("倒数第1个节点为:"+res);
}
//获取单链表的节点个数,如果是带头节点的链表就不统计头节点
public static int getLength(HeroNode head) {
if (head.next == null) {
//为空链表则直接返回0
return 0;
}
int length = 0;//统计有效节点个数
//辅助变量用于遍历
HeroNode current = head.next;
while (current != null) {
length++;
current = current.next;
}
return length;
}
//获取单链表倒数第K个节点
public static HeroNode findLastIndexNode(HeroNode head,int index){
//判断链表是否为空
if(head.next==null){
return null;
}
//先遍历得到节点个数
int Length=getLength(head);
//再遍历到size-index
if(index<=0||index>Length){
return null;//不合适的index就返回null
}
//定义辅助变量temp
HeroNode temp=head.next;
for(int i=0;i<Length-index;i++){
temp=temp.next;
}
return temp;
}
}
//英雄类
class HeroNode {
public int no;
public String name;
public String nickname;
public HeroNode next;//指向下一个节点
//构造器
public HeroNode(int hNo, String hName, String hNickname) {
this.no = hNo;
this.name = hName;
this.nickname = hNickname;
}
//重写toString来显示方法
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
}
}
//管理英雄类
class SingleLinkedList {
//先初始化头节点,不存放具体数据
private HeroNode head = new HeroNode(0, "", "");
//返回头节点
public HeroNode getHead() {
return head;
}
//添加节点。不考虑编号顺序时,先找到当前链表的最后节点,再将这个节点的next指向新节点
public void add(HeroNode heroNode) {
//辅助遍历temp
HeroNode temp = head;
//遍历链表找到最后
while (true) {
if (temp.next == null) {//找到最后了就退出
break;
}
//没到最后就后移到下一个节点
temp = temp.next;
}
//退出while循环时temp就指向链表最后
//我们要添加新节点,就将这个最后节点的next指向节点
temp.next = heroNode;
}
//添加节点,考虑编号顺序。也就是插入到链表非末尾位置
public void addByOrder(HeroNode heroNode) {
//辅助变量位于添加位置的前一个节点
HeroNode temp = head;
boolean flag = false;//标识添加的编号是否存在。如果存在就不能添加了
while (true) {
if (temp.next == null) {
//已经在链表最后,要添加的节点可能已经在链表最后
break;
}
if (temp.next.no > heroNode.no) {
//temp下一个节点的编号大于要插入的节点编号,就是找到了,要在这个temp后面插入
break;
} else if (temp.next.no == heroNode.no) {
//编号已存在
flag = true;//编号存在
}
temp = temp.next;//后移
}
//判断编号是否已存在
if (flag) {
System.out.printf("准备插入的编号 %d 已经存在,无法添加\n", heroNode.no);
} else {
//新节点插入链表中temp的后面
heroNode.next = temp.next;
temp.next = heroNode;//temp后面是新节点
}
}
//根据编号修改节点信息,即编号不能修改
public void update(HeroNode newHeroNode) {
//判断链表是否为空
if (head.next == null) {
//如果链表为空就不遍历了
System.out.println("链表为空");
return;
}
//找到需要修改的节点
//辅助变量
HeroNode temp = head.next;
boolean flag = false;//判断是否找到该节点
while (true) {
if (temp == null) {
break;//已经遍历完链表
}
if (temp.no == newHeroNode.no) {
//找到
flag = true;
break;
}
temp = temp.next;
}
//判断是否找到节点
if (flag) {
temp.name = newHeroNode.name;
temp.nickname = newHeroNode.nickname;
} else {
System.out.printf("没有找到编号为 %d 的节点\n", newHeroNode.no);
}
}
//删除节点
public void delete(int no) {
//判断链表是否为空
if (head.next == null) {
//如果链表为空就不遍历了
System.out.println("链表为空");
return;
}
//找到需要修改的节点
//辅助变量
HeroNode 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;
} else {
System.out.printf("没有找到编号为 %d 的节点\n", no);
}
}
//显示链表,看有没有成功
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;
}
}
}
运行结果:
题三:反转单链表
原链表:
反转后:
思路
先定义一个节点reverseHead=newHeroNode(),再遍历原来的链表,遍历一个节点就取出一个节点,放到新链表的最前端。最后使原来链表的head.next=reverseHead.next,就连上了。
一个辅助变量temp,指向要取出的节点之后把temp后移一个然后把节点取出来,把reverseHead节点与刚取出的节点连起来。
如图先把第一个节点获取之后接到reverseHead节点后面,temp已经移到了第二个节点。
再把获取的第二个节点接到reverseHead节点后面,第二个节点的next变成原来的第一个节点。
再把获取的第三个节点接到reverseHead节点后面,第三个节点的next变成原来的第二个节点。
最后把原head节点的next指向reverseHead节点的后面的第一个节点。那么从head节点开始遍历的时候也不会遍历到reverseHead节点。成功实现了链表反转。
关键代码:
//将链表反转
public static void reverseList(HeroNode head) {
//当前链表为空或只有一个节点就不需要反转
if (head.next == null || head.next.next == null) {
return;
}
//定义辅助变量遍历原来的链表
HeroNode current = head.next;
HeroNode curNext = null;//指向当前节点current的下一个节点
HeroNode reverseHead = new HeroNode(0, "", "");
//遍历原来的链表,遍历一个节点就取出一个节点放在新链表reverseHead最前面
while (current != null) {
curNext = current.next;//暂时保存当前节点的下一个节点
current.next = reverseHead.next;//将current的下一个节点指向新链表的最前端,就是新链表头节点后面的第一个节点
reverseHead.next=current;//将current连接到新链表上
current=curNext;//当前节点后移一个
}
//while这里结束之后就实现了完整的新链表
//将head.next指向reverseHead.next
head.next=reverseHead.next;
}
在main中:
//测试链表反转
singleLinkedList.list();
System.out.println("反转后:");
reverseList(singleLinkedList.getHead());
singleLinkedList.list();
反转单链表完整代码:
package com.xjj.linkedlist;
public class LinkedList {
public static void main(String[] args) {
//创建节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
//将节点加入链表
singleLinkedList.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
singleLinkedList.add(hero4);
//测试链表反转
singleLinkedList.list();
System.out.println("反转后:");
reverseList(singleLinkedList.getHead());
singleLinkedList.list();
}
//将链表反转
public static void reverseList(HeroNode head) {
//当前链表为空或只有一个节点就不需要反转
if (head.next == null || head.next.next == null) {
return;
}
//定义辅助变量遍历原来的链表
HeroNode current = head.next;
HeroNode curNext = null;//指向当前节点current的下一个节点
HeroNode reverseHead = new HeroNode(0, "", "");
//遍历原来的链表,遍历一个节点就取出一个节点放在新链表reverseHead最前面
while (current != null) {
curNext = current.next;//暂时保存当前节点的下一个节点
current.next = reverseHead.next;//将current的下一个节点指向新链表的最前端,就是新链表头节点后面的第一个节点
reverseHead.next=current;//将current连接到新链表上
current=curNext;//当前节点后移一个
}
//while这里结束之后就实现了完整的新链表
//将head.next指向reverseHead.next
head.next=reverseHead.next;
}
}
//英雄类
class HeroNode {
public int no;
public String name;
public String nickname;
public HeroNode next;//指向下一个节点
//构造器
public HeroNode(int hNo, String hName, String hNickname) {
this.no = hNo;
this.name = hName;
this.nickname = hNickname;
}
//重写toString来显示方法
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
}
}
//管理英雄类
class SingleLinkedList {
//先初始化头节点,不存放具体数据
private HeroNode head = new HeroNode(0, "", "");
//返回头节点
public HeroNode getHead() {
return head;
}
//添加节点。不考虑编号顺序时,先找到当前链表的最后节点,再将这个节点的next指向新节点
public void add(HeroNode heroNode) {
//辅助遍历temp
HeroNode temp = head;
//遍历链表找到最后
while (true) {
if (temp.next == null) {//找到最后了就退出
break;
}
//没到最后就后移到下一个节点
temp = temp.next;
}
//退出while循环时temp就指向链表最后
//我们要添加新节点,就将这个最后节点的next指向节点
temp.next = heroNode;
}
//显示链表,看有没有成功
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;
}
}
}
运行结果
加油加油^_^