avatar

java实现单链表

java实现单链表

废话不多说,直接上代码

package com.csw.LinkedList;

import jdk.nashorn.internal.ir.Flags;

import java.util.Stack;

/**
* @Auther: 行路
* @Date: Created on 2020/4/14 20:03:24
* @Description: com.csw.LinkedList 该链表按照添加顺序存储。
* @version: 1.0
*/
public class SIngleLinkedListDemo {
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.addByOrder(hero2);
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero3);

//修改前

singleLinkedList.list();

//测试修改节点的代码
HeroNode hero5=new HeroNode(2,"骁龙","855");
singleLinkedList.update(hero5);

System.out.println("~~~~~~~~");
//显示
singleLinkedList.del(4);
singleLinkedList.list();

System.out.println("有效节点的个数"+getLength(singleLinkedList.getHead()));

System.out.println("测试得到倒数第k个");
HeroNode res=findLastIndexNode(singleLinkedList.getHead(),3);
System.out.println(res);


System.out.println("逆序打印");
reversePrint(singleLinkedList.getHead()); //没有改变链表的本身结构

System.out.println("测试反转");
reversetList(singleLinkedList.getHead());
singleLinkedList.list();


}


/**
* //方法,获取单链表的节点个数(如果带头节点的链表,需求不统计头节点)
*这是一个方法,返回单链表的有效的节点个数
* @param head 链表的头节点
* @return 返回的是有效节点的个数
*/
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;
}



/**
* //查找单链表中的倒数第k个结点(新浪面试题)
* //思路
* //1.编写一个方法,接收head节点,同时接收一个index
* //2.index 表示是倒数第Index个节点
* //3.先把链表从头到尾遍历,得到链表的总长度,getLength
* //4.得到size后,我们从链表的第一个开始遍历(size-index)个,就可以得到
* //5,如果找到了,则返回该节点,否则返回null
* @param head
* @param index
* @return
*/
public static HeroNode findLastIndexNode(HeroNode head,int index){
//判断如果链表为空,返回null
if(head.next==null){
return null; //没有找到
}
//第一次遍历得到的链表的长度(节点的个数)
int size=getLength(head);
//第二次遍历 size-index位置,就是我们倒数的第k个节点
//先做一个(index)数据的校验
if(index<=0||index>size){
return null;
}
//定义一个辅助变量,for循环定位到倒数的Index
HeroNode cur=head.next;
for(int i=0;i<size-index;i++){
cur=cur.next;
}
return cur;

}


//将单链表进行反转
public static void reversetList(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连接到新的链表上
cur=next; //让cur指向下一个节点,后移一次
}
//将head.next指向reverseHead.next,实现单链表的反转
head.next=reverseHead.next;
}

//从尾到头打印单链表(逆序打印单链表)
//方式一:先将单链表进行反转,然后再遍历,破坏原来的单链表的结构
//方式二:利用栈,将各个节点压入栈,然后利用栈的先进后厨特点,实现逆序打印的效果。
//使用方式二
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; //将cur后移,这样就可以压入下一个节点
}
//将栈中的节点进行打印pop出栈
while (stack.size()>0){
System.out.println(stack.pop()); //stack的特点是先进后厨
}
}



}

//定义SingleLinkedList管理我们的英雄
class SingleLinkedList{
//先创建一个头节点,头节点不要动
private HeroNode head=new HeroNode(0,"","");

//返回头节点
public HeroNode getHead() {
return head;
}

public void setHead(HeroNode head) {
this.head = head;
}

//添加节点到单向链表
//思路,当不考虑编号顺序
//1.找到当前链表的最后节点
//2.将最后这个节点的next,指向新的链表
public void add(HeroNode heroNode){
//因为head节点不能动,因此我们需要一个辅助遍历temp
HeroNode temp=head;

//遍历链表,找到最后
while (true){

//找到链表的最后
if(temp.next==null){
break;
}
//如果没有找到最后,就将temp后移
temp=temp.next;
}
//当退出while循环时,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){ //说明希望添加的heroNode的编号已经存在
flag=true; //说明编号存在
break;
}
temp=temp.next; //后移,遍历当前链表
}
//判断flag的值
if(flag){ //不能添加,说明编号已经存在
System.out.println("准备插入的人的编号已经存在,不能加入,"+heroNode.no);
}else{
//插入到链表中,temp的后边
heroNode.next=temp.next;
temp.next=heroNode;

}
}

//删除节点
//思路
//1.head节点不能动,因此需要一个temp辅助节点,找到待删除节点的前一个节点
//2.说明我们在比较时,是temp.next.no和要删除的节点的no比较
public void del(int no){
HeroNode temp=head;
boolean flag=false; //标识是否找到待删除节点
while(true){
if(temp.next==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);
}
}


//修改节点的信息,根据编号来修改,即no编号不能改
//说明:根据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);
}
}


//显示链表[遍历]
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.toString());
//将temp后移
temp=temp.next;
}
}



}


//定义一个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;
}

@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
文章作者: Todcsw
文章链接: https://todcsw.github.io/2020/04/14/dataStructure-java%E5%AE%9E%E7%8E%B0%E5%8D%95%E9%93%BE%E8%A1%A8/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 行路のblog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论