关于链表的一些操作

阅读 199

2022-03-11

        还差一个功能没写,好像是哪个的面试题,晚上重新给补充上。其余的东西注释写的方法功能,以及分析都写在代码里面了。

package linkedListDemo;

/**
* 在本类中,定义一个英雄节点。使用链表存储
* 使用链表完成:
* 1.添加新节点进链表;
* 2.添加新节点进链表并且需要按照编号排序添加进去;
* 3.修改链表中英雄节点的数据(根据编号)
* 4.删除指定编号的英雄节点
* 5.查询指定节点的英雄数据
*/


public class HeroNodeDemo {
public static void main(String[] args) {
SingleLinkedList hero = new SingleLinkedList();
HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
HeroNode hero3 = new HeroNode(3,"吴用","智多星");
HeroNode hero4 = new HeroNode(4,"林冲","豹子头");
hero.addByOrder(hero1);
hero.addByOrder(hero4);
hero.addByOrder(hero2);
hero.addByOrder(hero3);
hero.list();
System.out.println("===============");

hero.del(2);
hero.list();
System.out.println("===============");
HeroNode hero_4 = new HeroNode(4,"鲁智深","花和尚");
hero.update(hero_4);
hero.list();
System.out.println("===============");

hero.find(4);
System.out.println("===============");
int length = hero.getLength();
System.out.println("链表的长度为:"+length);
System.out.println("===============");
hero.reverseLinkedList();
hero.list();
System.out.println("===============");
HeroNode lastK = hero.getLastK(2);
System.out.println(lastK);

}
}


//定义一个单链表类,里面需要写很多关于链表的操作方法
class SingleLinkedList{
//创建一个头节点(头节点不包含任何数据,只是提供一个指针域指向链表第一个节点,而且不能动)
private HeroNode head = new HeroNode(0,"","");

//往链表添加数据
public void add(HeroNode heroNode){
//王链表添加数据的话,首先找到链表的末尾元素,然后把这个元素的指针域指向这个对象就好
HeroNode temp = head;
while(true){
if(temp.next == null){
break;
}
temp = temp.next;
}
temp.next = heroNode;
}
//根据编号顺序添加元素进入链表
/*
分析:
1.先判断链表为空,就直接加入
2.链表不为空时,用一个指针指向第一个节点,如果出现temp.no == hero.no,就输出英雄重复;
3.判断temp.next.no < hero.no && temp.no < hero.no,这种就可以添加进去
4.如果到了最后temp.no < hero.no,就直接添加到末尾
*/

public void addByOrder(HeroNode heroNode){
HeroNode temp = head;
boolean flag = false;
while(true){
if(temp.next == null){
//已经到了链表的末尾
break;
}
if(temp.next.no > heroNode.no){
//如果是当前节点的下一个节点的no大于当前插入节点,那么temp就到了位置了
break;
}else if(temp.next.no == heroNode.no){
//如果是当前节点的下一个节点的no等于当前插入节点,那么就打印错误信息
flag = true;
break;
}
temp = temp.next;
}
if(flag){
//no重复,插入不了
System.out.println("已有该编号,插入失败...");
return;
}else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}

//删除指定编号的节点对象
/*
分析:
1.由于是单链表,我要是删除指定位置的结点的话,我就需要temp.next.no = no,删除
*/

public void del(int no){
if(head.next == null){
System.out.println("空链表,不能删除...");
return;
}
HeroNode cur = head;//直接指向头节点,防止删除的元素是第一个
boolean flag = false;//防止找不到元素,打印错误信息
while(true){
if(cur.next.no == no){
//找到元素
flag = true;
break;
}
cur = cur.next;
}
if(flag){
cur.next = cur.next.next;
}else{
System.out.println("没找到指定编号的节点...");
return;
}
}
//修改指定编号的数值

/*
分析:
1.遍历链表,找到指定no的节点,如果没找到,那就是返回错误信息
*/

public void update(HeroNode heroNode){
if(head.next == null){
System.out.println("空链表,无法修改数据...");
return;
}
HeroNode cur = head;
boolean flag = false;
while(true){
if(cur.next == null){
break;
}
if(cur.next.no == heroNode.no){
//找到了指定编号的对象,可以修改数据,肯定是修改当前的节点数据
flag = true;
cur = cur.next;
break;
}
cur = cur.next;
}
if(flag){
//找到编号,修改数据
cur.name = heroNode.name;
cur.nickName = heroNode.nickName;
}else{
System.out.println("没有指定编号的数据,修改失败...");
return;
}
}

//查询指定编号的节点对象的数据
/*
分析:
1.只是返回对象的话,打印就好了,而且我重写了toString;
2.只要找到指定no的对象就好了,很简单
*/

public void find(int no){
if(head.next == null){
System.out.println("链表为空,无法查询...");
return;
}
HeroNode temp = head.next;
boolean flag = false;
while(true){

if(temp.no == no){
flag = true;
break;
}
if(temp.next == null){
//当前是链表的组后一个数据,还没找到,就打印错误信息
break;
}
temp = temp.next;
}
if(flag){
//输出当前temp
System.out.println(temp);
}else{
System.out.println("未找到指定编号的节点...");
return;
}
}

//返回链表的长度
/*
分析:
1.听说这个是新浪的面试题
2.如果是查询链表长度的话,就是一直遍历到末尾,然后搞一个计数器在那累加就i好
*/

public int getLength(){
if(head.next == null){
return 0;
}
HeroNode temp = head;
int count = 0;
while(true){
if(temp.next == null){
//如果是当前元素为链表最后一个结点的话,那么就可以返回count
break;
}
temp = temp.next;
count ++;
}
return count;
}
//得到链表倒数第k个结点的数据
/*
分析:
1.遍历数组,其实就是获取第getLength - index位置的数据
2.特殊情况:
index > getLength() || index < 0都是要打印错误信息的
*/

public HeroNode getLastK(int index){
int size = getLength();
if(head.next == null){
System.out.println("链表为空,获取不到数据...");
return null;
}
if(index < 0 || index > size){
System.out.println("索引是错误的,无法查找数据...");
return null;
}

HeroNode temp = head.next;
int count = 0;
int fin = size - index;// 3 - 1 = 2;宋江
while(true){
if(count < fin){
count ++;
temp = temp.next;
}else{
break;
}
}
return temp;
}

//反转链表 4 -> 3 -> 1
/*
分析:
1.如果要是反转链表的话,就是先创建一个新的头节点reverseNode;
2.遍历原来的链表,除开头节点外,每遍历到一个元素,就把他给取下来,街道reverseNode的后边;
3.在上面那个步骤中,需要多创建一个节点用于保存被取下元素的下一个结点的地址;
4.遍历完成之后,将head.next = reverseNode.next;reverseNode.next = null;
*/

public void reverseLinkedList(){

if(head.next == null || head.next.next == null){
return;
}
HeroNode reverseNode = new HeroNode(0,"","");
HeroNode temp = head.next;
HeroNode next = null;

while(temp != null){
next = temp.next;
temp.next = reverseNode.next;
reverseNode.next = temp;
temp = next;
}

head.next = reverseNode.next;
reverseNode.next = null;
}


//显式链表数据
//这个是用来遍历链表的方法
/*
分析:判断temp.next == null,就停止遍历
*/

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;
}
}

}

/*
定义一个英雄节点:包含编号,姓名,绰号,还有指向下一个英雄结点的对象
*/

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 + '\'' +
'}';
}



}

精彩评论(0)

0 0 举报