链表的基本操作
添加节点
默认添加到链表最后
public void add(HeroNode heroNode){
//因为头节点不能动 我们需要一个辅助变量Temp
HeroNode temp = head;
//遍历链表找到最后
while (true){
//找到链表最后
if(temp.next==null){
break;
}
//没有找到最后的时候Temp后移
temp = temp.next;
}
temp.next = heroNode;
}
按链表中的某个信息按顺序添加
示例中按照的是HeroNode中的no顺序添加
public void addByOrder(HeroNode heroNode){
//头节点不能动需要定义辅助变量
//单链表,因此找的Temp是位于添加位置的前一个节点否则插入不了
HeroNode temp = head;
boolean flag = false;//标识所需要添加的编号是否存在默认为false
while (true){
if(temp.next == null){//说明此时temp在链表的最后
break;
}
if(temp.next.no > heroNode.no){//位置找到就在temp的后面插入
break;
}
else if(temp.next.no == heroNode.no){//该节点的编号已经存在
flag = true;//说明编号存在System.out.println("该节点的编号已经存在");
break;
}
temp = temp.next;
}
if(flag == true){
System.out.println("准备插入的编号已经存在" + heroNode.no);
}
else {
//可以插入
heroNode.next = temp.next;
temp.next = heroNode;
}
}
删除节点
示例中的根据节点的no来查找删除
public void deleteHeroNode(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.println("需要删除的节点不存在");
}
}
//显示链表遍历
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);
//将next后移
temp = temp.next;
}
}
修改链表中的信息
示例中根据节点的no来修改节点的信息
public void update(HeroNode newHeroNode){
//判断是否为空
if(head.next == null){
System.out.println("链表为空·····");
return;
}
HeroNode temp = head;
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.println("没有找到编号为"+ newHeroNode.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);
//将next后移
temp = temp.next;
}
}
具体的示例
package com.yc.day01.linkList;
/*
@ClassName HeroNode
@author cc
@Date 2020-07-29 13:22
@Version 1.0
1.创建一个head头节点作用就是表示链表的头
2.后面我们每添加一个节点直接就添加到链表的最后
遍历
1.
顺序添加节点
1.首先要找到新节点添加的位置 是通过辅助变量(指针) 通过遍历来确定
2.新的节点的next域指向temp的next域
3.将temp.next=新节点
双向链表
1.遍历和单向链表一样 不同:可以向前也可以先后查找
2.添加(默认添加到双向链表的最后)
1).先找到双向链表的最后节点
2).temp.next = new heroNode
3).newHeroNode.pro = temp
3.修改 和单线链表思路一致
4.删除
1).双向链表 可以实现自我删除某个节点
2).直接找到要删除的节点如:temp
3).temp.pro.next = temp.next
4).temp.next.pro = temp.pro
*/
import java.util.Stack;
public class SingleLinkedListDome {
public static void main(String[] args) {
//测试
//创建节点
HeroNode heroNode1 = new HeroNode(1, "宋江", "及时雨");
HeroNode heroNode2 = new HeroNode(2,"卢俊义","玉麒麟");
HeroNode heroNode3 = new HeroNode(3,"吴用","智多星");
HeroNode heroNode4 = new HeroNode(4,"林冲","豹子头");
//HeroNode newHeroNode = new HeroNode(4,"林冲","32145636524");
//创建给链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
/*singleLinkedList.add(heroNode1);
singleLinkedList.add(heroNode4);
singleLinkedList.add(heroNode2);
singleLinkedList.add(heroNode3);*/
singleLinkedList.addByOrder(heroNode1);
singleLinkedList.addByOrder(heroNode4);
singleLinkedList.addByOrder(heroNode2);
singleLinkedList.addByOrder(heroNode3);
//singleLinkedList.addByOrder(heroNode3);
//测试逆序打印单链表
/*System.out.println("原来链表的情况-------------");
singleLinkedList.list();
System.out.println("逆序打印单链表-------------");
reversePrint(singleLinkedList.getHead());*/
singleLinkedList.deleteHeroNode(2);
System.out.println("删除后链表的情况-------------");
singleLinkedList.list();
/*//测试单链表反转
System.out.println("原来链表的情况");
singleLinkedList.list();
System.out.println("反转链表-------------------------");
reverseList(singleLinkedList.getHead());
singleLinkedList.list();*/
/*System.out.println("-----------------------------");
singleLinkedList.update(newHeroNode);
singleLinkedList.list();
System.out.println("----------------------");
System.out.println("当前的的节点个数为"+getLength(singleLinkedList.getHead()));
HeroNode res = findLastIndexNode(singleLinkedList.getHead(),2);
System.out.println("倒数第"+res+"个节点");*/
}
//查找单链表的倒数第K个节点
/*
* 1.编写一个方法接收head节点 同时接收一个index
* 2.index是表示倒数index节点
* 3.把链表从头到尾遍历 得到链表的总长度 getLength
* 4.得到Size后 从链表的第一个开始遍历(Size - Index)个就可以得到
* 5.如果找到了就返回该节点 否则返回Null
* */
public static HeroNode findLastIndexNode(HeroNode head,int index){
//判断链表是否为空
if(head.next == null){
return null;
}
//遍历得到链表的长度
int size =getLength(head);
//第二次遍历 size-index 位置 就是我们需要的倒数第K个节点
//先做一个数据校验
if(index <= 0 || index>size){
return null;
}
//定义一个辅助变量使用for循坏定位到倒数第K个节点
HeroNode cur = head.next;//指向第一个有效节点
for(int i=0;i < size-index; i++){
cur = cur.next;
}
return cur;
}
/*
* 1.定义一个节点reverseHead = new HeroNode();
* 2.从头遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表的最前端
* 3.原来链表的Head.next = reverseHead.next
* 4.
* */
//单链表反转
public static void reverseList(HeroNode head){
//如果当前的链表为空或者只有一个节点的无需反转直接放回
if(head.next == null || head.next.next == null){
return;
}
//定义一个辅助变量帮助我们遍历原来的链表
HeroNode cur = head.next;
HeroNode next =null;//指向当前节点cur的下一个节点
HeroNode reverseHead = new HeroNode(0,"","");
//遍历原来的链表每遍历一个节点就将其取出放在新链表reverseHead的最前端
while (cur != null){
next = cur.next;//保存当前节点的下一个节点 后面需要使用
cur.next = reverseHead.next;//将cur的下一个节点指向新的链表的头部
reverseHead.next = cur;//将cur连接到reverseHead链表上
cur =cur.next;
}
//将head.next指向reverseHead.next 实现链表反转
head.next = reverseHead.next;
}
//有效节点的个数
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;
}
/*
* 逆序打印单链表
* 方式一:将单链表反转之后打印单链表
* 问题:会破坏原来单链表的结构
* 方式二:利用栈这个数据结构将各个节点压入栈中
* 然后利用栈先进后出的特点实现逆序打印
* Stack 栈
* */
//使用方式二来实现
public static void reversePrint(HeroNode head){
if(head.next == null){
return; //空链表
}
//创建一个栈
Stack<HeroNode> stack = new Stack<>();
HeroNode cur =head.next;
while (cur != null){
stack.push(cur);
cur = cur.next;
}
//将栈中的节点打印
while (stack.size()>0){
System.out.println(stack.pop());
}
}
}
//定义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 + '\'' +
'}';
}
}
class SingleLinkedList{
//定义一个头节点 头节点不动
private HeroNode head = new HeroNode
(0,"","");
//返回头节点
public HeroNode getHead() {
return head;
}
//添加节点方法
//1.不考虑编号顺序
//2.将最后的节点的next指向新节点
public void add(HeroNode heroNode){
//因为头节点不能动 我们需要一个辅助变量Temp
HeroNode temp = head;
//遍历链表找到最后
while (true){
//找到链表最后
if(temp.next==null){
break;
}
//没有找到最后的时候Temp后移
temp = temp.next;
}
temp.next = heroNode;
}
//顺序添加节点的方式
//根据对象里面的字段来进行排序插入(有重复的时候提示添加失败)
public void addByOrder(HeroNode heroNode){
//头节点不能动需要定义辅助变量
//单链表,因此找的Temp是位于添加位置的前一个节点否则插入不了
HeroNode temp = head;
boolean flag = false;//标识所需要添加的编号是否存在默认为false
while (true){
if(temp.next == null){//说明此时temp在链表的最后
break;
}
if(temp.next.no > heroNode.no){//位置找到就在temp的后面插入
break;
}
else if(temp.next.no == heroNode.no){//该节点的编号已经存在
flag = true;//说明编号存在System.out.println("该节点的编号已经存在");
break;
}
temp = temp.next;
}
if(flag == true){
System.out.println("准备插入的编号已经存在" + heroNode.no);
}
else {
//可以插入
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//修改节点,根据编号来修改
public void update(HeroNode newHeroNode){
//判断是否为空
if(head.next == null){
System.out.println("链表为空·····");
return;
}
HeroNode temp = head;
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.println("没有找到编号为"+ newHeroNode.no + "的节点");
}
}
//删除节点
/*
1.先找到需要删除的这个节点的前一个节点temp
2.temp.next = temp.next.next
3.被删除的节点将不会有其他应用会被垃圾回收机制回收
* */
public void deleteHeroNode(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.println("需要删除的节点不存在");
}
}
//显示链表遍历
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);
//将next后移
temp = temp.next;
}
}
}