当前位置 博文首页 > 邱天的henry的博客:第三章 数据结构与算法(链表)
3.1链表(Linked List)介绍
ps:后面实现链表需先创建节点类,然后在创建链表
链表是有序的列表,但是它在内存中存储如下:
小结上图:
@单链表(带头结点)逻辑结构示意图如下
3.2单链表的应用实例
使用带head头的单向链表实现 -水浒英雄排行榜管理完成对英雄人物的增删改查操作。
(1)第一种方法在添加英雄时,直接添加到链表的尾部
思路分析示意图:
(2)第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
思路分析示意图:
(3)修改节点功能
思路1.先找到该节点(通过遍历)2.temp.name=newHeroNode.name;temp.nickname=newHeroNode.nickname
(4)删除节点
思路分析示意图:
(5)实现代码演示:
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, "林冲", "豹子头");
HeroNode hero5 = new HeroNode(3, "孙悟空", "美猴王");
//创建链表
SingleHeroNode singleHeroNode = new SingleHeroNode();
// singleHeroNode.add(hero1);
// singleHeroNode.add(hero2);
// singleHeroNode.add(hero3);
// singleHeroNode.add(hero4);
singleHeroNode.addByOrder(hero2);
singleHeroNode.addByOrder(hero1);
singleHeroNode.addByOrder(hero3);
singleHeroNode.addByOrder(hero4);
//singleHeroNode.addByOrder(hero5);
singleHeroNode.update(hero5);
singleHeroNode.delete(1);
singleHeroNode.delete(2);
singleHeroNode.delete(3);
singleHeroNode.delete(4);
//展示
singleHeroNode.list();
}
}
//创建单链表
class SingleHeroNode{
//首先定义头结点,头结点用来标记不可移动,所以下面遍历都需重新定义变量temp
private HeroNode head=new HeroNode(0,"","");
//添加节点方式一:不考虑顺序
//1.首先定义一个临时变量temp来遍历链表(节点需要添加到末尾遍历出next为null的节点)
//2.将节点添加
public void add(HeroNode node){
HeroNode temp=head;
//一直循环遍历
while (true){
if (temp.next==null){
break;
}
//如果没有找到,则将此指针后移
temp=temp.next;
}
temp.next=node;
}
//添加节点方式二:考虑节点的顺序(按照节点的编号进行添加)
//如果编号已经存在,则提示添加失败
public void addByOrder(HeroNode node){
//因为头结点不可移动,所以需定义变量temp来进行遍历
HeroNode temp=head;
boolean flag=false; //定义标识符来标识添加的英雄编号是否存在
//遍历找到加入节点位置的前一个位置
while (true){
if (temp.next==null){
break; //遍历到节点末尾
}
if (temp.next.no>node.no){
break; //说明加入节点位置的前一个节点找到
}else if (temp.next.no==node.no){
flag=true;
break; //加入英雄的编号已经存在,添加失败
}
temp=temp.next; //以上条件不满足,指针下移
}
if (flag){
System.out.printf("添加的英雄编号%d已经存在,添加失败\n",node.no);
}else {
node.next=temp.next;
temp.next=node;
}
}
//修改英雄信息(根据英雄的no修改英雄的名字和别名)
public void update(HeroNode newHerNode){
//定义变量temp方便遍历
HeroNode temp=head;
boolean falg=false; //标识找到指定的英雄节点
while (true){
if (temp.next==null){
break; //遍历到结尾,没有此结点
}
if (temp.next.no==newHerNode.no){
falg=true; //标识已经找到
break;
}
temp=temp.next;
}
if (falg){
temp.next.name=newHerNode.name;
temp.next.nickName=newHerNode.nickName;
}else {
System.out.printf("没有%号的英雄节点,修改失败\n",newHerNode.no);
}
}
//删除节点(遍历找到待删除节点的前一个节点)
public void delete(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; //不满足条件后移
}
if (flag){
temp.next=temp.next.next; //删除元素
}else {
System.out.printf("没有%d号英雄节点,删除失败\n",no);
}
}
//遍历节点
public void list(){
HeroNode temp=head;
if (temp.next==null){
System.out.println("单链表为空");
}
while (true){
if (temp.next==null){
break;
}
System.out.println(temp.next); //注意此处temp定义的头结点,所以打印temp.next
temp=temp.next;
}
}
}
//创建类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方法(因为此类中有next属性,为了防止重复打印后面的节点,所以省略next)
@Override
public String toString() {
return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickName='" + nickName + '\'' + '}';
}
}
单链表*面试题(新浪、百度、腾讯)
单链表的常见面试题有如下:
(1)求单链表中有效节点的个数
(2)查找单链表中的倒数第K个节点【新浪面试题】
(3)单链表的反转【腾讯面试题,有点难度】
(4)从尾到头打印单链表【百度,要求方式1;反向遍历。方式2:Stack栈】
代码:为了方便书写和观看,上述的题目直接写在实现单链表的上面
package com.itcast.linkedList;
import java.util.Stack;
public class SingleLinkedListDemo {
public static void main(String[] args) {
//测试,先创建节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(