基础知识

大体结构和C++的链表差不多

补充之前不知道的:链表分两类,带和不带头结点的链表 现在才知道,Java没有像C/C++那样的指针

首先创建一个LinkList类,然后把链表的各个功能添加进去

创建结点

//当不考虑编号顺序时,找到当前链表最后节点,将最后节点next指向新节点
public void add(PersonNode node) {
//因为头节点不能动,先需要一个辅助遍历节点temp
PersonNode temp = head;
while (true) {//遍历链表,找到最后
if (temp.next == null) {
break;
}
temp = temp.next;//如果没到最后,就继续找下去
}//当退出while循环时,temp指向链表的最后
temp.next = node;
}

添加结点(乱序)

public void addByOrder(PersonNode node) {
//因为头节点不移动,仍通过一个辅助变量来找添加的位置
//因为是单链表,所以找的temp时位于添加位置的前一个结点,否则不能插入
PersonNode temp = head;
boolean flag = false;//标识添加的编号是否存在
while (true) {
if (temp.next == null) //说明temp在链表最后
break;
if (temp.next.no > node.no) {//位置找到了,就在temp后面
break;
} else if (temp.next.no == node.no) {//希望添加的编号已存在
flag = true;
break;
}
temp = temp.next;
}
if (flag) {//编号已存在,不能添加
System.out.println("already exist no." + node.no + ", you can't add it.=====");
} else {
node.next = temp.next;
temp.next = node;
}
}//最终还是按照序号来排列

编辑结点

public void edit(PersonNode node) {//这里直接引入外部结点,根据node.no来寻找需要修改的结点
if (head.next == null) {
System.out.println("empty LinkList====");
return;
}
PersonNode temp;
temp = head.next;
boolean flag = false;//判断是否找到该结点
while (true) {
if (temp == null)
break;//到了链表最后
if (temp.no == node.no) {
flag = true;//找到
break;
}
temp = temp.next;
}
//根据flag判断是否找到
if (flag) {
temp.name = node.name;
temp.score = node.score;
} else {
System.out.println("not found no." + node.no + "====");
}
System.out.println("=======");
}

删除结点

public void delete(int no) {
if (head.next == null) {
System.out.println("empty LinkList===");
return;
}
PersonNode temp = head;//temp指向待删除结点的前一个结点
boolean flag = false;
while (true) {
if (temp.next == null) {
break;//已经到链表最后
}
if (temp.next.no == no) {
flag = true;//找到了待删除结点的前一个结点temp
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
//Java会自动回收未被访问的数据
} else {
System.out.println("not found====");
}
System.out.println("====");
}

打印链表

public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("empty LinkList=====");
return;
}
//头节点不动,需要一个辅助变量来遍历
PersonNode temp = head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//由于之前重写了toString,这里直接打印temp就可以打印出节点的所有信息
temp = temp.next;
}
}

主函数

public static void main(String[] args) {
PersonNode person1 = new PersonNode(1, "Jordan", 56);
PersonNode person2 = new PersonNode(2, "Kobe", 81);
PersonNode person3 = new PersonNode(3, "James", 61);
PersonNode person4 = new PersonNode(4, "Melo", 60);
LinkList list = new LinkList();
//按照顺序添加
// System.out.println("====add====");
// list.add(person1);
// list.add(person2);
// list.add(person3);
// list.add(person4);
//不按照顺序添加
System.out.println("====add by order====");
list.addByOrder(person1);
list.addByOrder(person4);
list.addByOrder(person3);
list.addByOrder(person2);
list.list();
// list.addByOrder(person2);
System.out.println("====edit====");
PersonNode newNode = new PersonNode(3, "Ivring", 57);
list.edit(newNode);
list.list();
//删除结点
System.out.println("====delete====");
list.delete(4);
list.list();
}

完整代码

//SingleLinkList.java
public class SingleLinkList {
public static void main(String[] args) {
PersonNode person1 = new PersonNode(1, "Jordan", 56);
PersonNode person2 = new PersonNode(2, "Kobe", 81);
PersonNode person3 = new PersonNode(3, "James", 61);
PersonNode person4 = new PersonNode(4, "Melo", 60);
LinkList list = new LinkList();
//按照顺序添加
// System.out.println("====add====");
// list.add(person1);
// list.add(person2);
// list.add(person3);
// list.add(person4);
//不按照顺序添加
System.out.println("====add by order====");
list.addByOrder(person1);
list.addByOrder(person4);
list.addByOrder(person3);
list.addByOrder(person2);
list.list();
// list.addByOrder(person2);
System.out.println("====edit====");
PersonNode newNode = new PersonNode(3, "Ivring", 57);
list.edit(newNode);
list.list();
//删除结点
System.out.println("====delete====");
list.delete(4);
list.list();
}
}
//定义一个成员点
class PersonNode {
String name;
public int no;
public int score;
public PersonNode next;//指向下一个结点 public PersonNode(int no, String name, int score) {
this.no = no;
this.name = name;
this.score = score;
}
//为了显示方便,重写toString
@Override
public String toString() {
return "[no=" + no + ",name=" + name + ",score=" + score + "]";
}
}
//定义LinkList管理person
class LinkList {
//初始化头节点,头节点不能动
private PersonNode head = new PersonNode(0, "", 0);
public PersonNode getHead(){
return head;//返回私有成员head
}
//当不考虑编号顺序时,找到当前链表最后节点,将最后节点next指向新节点
public void add(PersonNode node) {
//因为头节点不能动,先需要一个辅助遍历节点temp
PersonNode temp = head;
while (true) {//遍历链表,找到最后
if (temp.next == null) {
break;
}
temp = temp.next;//如果没到最后,就继续找下去
}//当退出while循环时,temp指向链表的最后
temp.next = node;
} public void addByOrder(PersonNode node) {
//因为头节点不移动,仍通过一个辅助变量来找添加的位置
//因为是单链表,所以找的temp时位于添加位置的前一个结点,否则不能插入
PersonNode temp = head;
boolean flag = false;//标识添加的编号是否存在
while (true) {
if (temp.next == null) //说明temp在链表最后
break;
if (temp.next.no > node.no) {//位置找到了,就在temp后面
break;
} else if (temp.next.no == node.no) {//希望添加的编号已存在
flag = true;
break;
}
temp = temp.next;
}
if (flag) {//编号已存在,不能添加
System.out.println("already exist no." + node.no + ", you can't add it.=====");
} else {
node.next = temp.next;
temp.next = node;
}
} public void edit(PersonNode node) {
if (head.next == null) {
System.out.println("empty LinkList====");
return;
}
PersonNode temp;
temp = head.next;
boolean flag = false;//判断是否找到该结点
while (true) {
if (temp == null)
break;//到了链表最后
if (temp.no == node.no) {
flag = true;//找到
break;
}
temp = temp.next;
}
//根据flag判断是否找到
if (flag) {
temp.name = node.name;
temp.score = node.score;
} else {
System.out.println("not found no." + node.no + "====");
}
System.out.println("=======");
} public void delete(int no) {
if (head.next == null) {
System.out.println("empty LinkList===");
return;
}
PersonNode temp = head;//temp指向待删除结点的前一个结点
boolean flag = false;
while (true) {
if (temp.next == null) {
break;//已经到链表最后
}
if (temp.next.no == no) {
flag = true;//找到了待删除结点的前一个结点temp
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("not found====");
}
System.out.println("====");
//Java会自动回收未被访问的数据
} //显示链表(遍历)
public void list() {
//判断链表是否为空
if (head.next == null) {
System.out.println("empty LinkList=====");
return;
}
//头节点不动,需要一个辅助变量来遍历
PersonNode temp = head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//由于之前重写了toString,这里直接打印temp就可以打印出节点的所有信息
temp = temp.next;
}
} }

面试题

求单链表中有效结点个数

//如果带头节点的链表,不统计头节点
public static int getLength(PersonNode head) {
if (head.next == null)
return 0;
int length = 0;
PersonNode current = head.next;//定义辅助变量
while (current != null) {
length++;
current = current.next;
}
return length;
}

在主函数中测试

System.out.println(getLength(list.getHead()));

查找单链表中倒数第n个结点(新浪)

思路

  • 编写一个方法,接收head结点,同时接收一个index
  • index表示是倒数第index个结点
  • 先把链表从头到尾遍历,得到链表的总长度 getLength
  • 得到size后,我们从链表第一个开始遍历(size-index)
public static PersonNode findLastIndexNode(PersonNode head, int index){
if (head.next == null)
return null;
int size = getlength(head);//第一次遍历,获取链表大小
if (index <= 0 || index > size)//判断倒数的序号是否超出容量
return null;
PersonNode current = head.next;
for (int i = 0; i < size - index; i++) {
current = current.next;//遍历size-index次
}
return current;
}

测试

PersonNode res = findLastIndexNode(list.getHead(), 1);
System.out.println(res);

单链表反转(腾讯)

思路

  • 先定义一个结点reverseHead = new PersonNode();
  • 从头到尾遍历原来的链表,每遍历一个链表,就将其取出,放在新链表最前端
  • 原来链表的head.next = reverseHead.next;
public static void reverseList(PersonNode head) {
if (head.next == null || head.next.next == null)
return;
// 定义一个辅助遍历,帮助遍历原来的链表
PersonNode current = head.next;
PersonNode next = null;//指向当前结点[current]的下一个结点
PersonNode reverseHead = new PersonNode(0, "", 0);
while (current != null) {
next = current.next;//先暂时保存当前结点的下一个结点,后面会用到
current.next = reverseHead.next;//把current的下一个结点指向新链表最前端
reverseHead.next = current;//将current连接到新链表
current = next;//让current后移
/*每一次循环,reverseHead.next都会按照原链表的顺序定位到current,遍历结束,刚到reverseHead.next定位到链表最后一个,
此时把reverseHead.next地址赋给head.next,这样就可以倒着来遍历链表*/ }
head.next = reverseHead.next;//头结点拼接,实现反转
}

测试

reverseList(list.getHead());
list.list();

从尾到头打印单链表(百度)

思路

  • 1.先反转后再打印(有个问题:只要求逆序打印,不要求反转,这样会破坏原链表结构)
  • 2.用栈的方法,利用栈先进后出的特点,实现逆序打印的效果

stack.java

下面是栈的实例

import java.util.Stack;
public class stack{
public static void main(String[] args){
Stack<String> stack = new Stack<>();
stack.add("James");
stack.add("Kboe");
stack.add("Jordan");
while(stack.size() > 0){
System.out.println(stack.pop());
}
}
}

用栈的方法实现从头到尾打印单链表

public static void reversePrint(PersonNode head) {
if (head.next == null)
return;
//创建一个栈,将各个结点压入栈
Stack<PersonNode> stack = new Stack<PersonNode>();
PersonNode current = head.next;
while (current != null) {
stack.push(current);
current = current.next;
}
while (stack.size() > 0) {
System.out.println(stack.pop());
}
}

测试

reversePrint(list.getHead());

单链表(Java--尚硅谷)的更多相关文章

  1. 数据结构——单链表java简易实现

    巩固数据结构 单链表java实现 单链表除了表尾 每个几点都有一个后继 结点有数据和后继指针组成  通过构建表头和表尾(尾部追加需要)两个特殊几点 实现单链表的一些操作,代码如下 package co ...

  2. 单链表---java实现

    单链表优点:1.不需要预先给出元素个数. 2.单链表插入删除时不需要移动数据元素. 单链表缺点:1.每个节点有指针,空间利用率低. 2.单链表不支持随机读取数据. Node.java package ...

  3. 单链表Java实现

    近期在复习基本数据结构,本文是单链表的Java实现,包含对单链表的实现插入删除查找遍历等.最后还实现了单链表的逆置. 实现了多项式相加,多项式相乘. 原文章及完整源码在这里 http://binhua ...

  4. 尚硅谷全套课件整理:Java、前端、大数据、安卓、面试题

    目录 Java 尚硅谷 IT 精英计划 JavaSE 内部学习笔记.pdf 尚硅谷 Java 基础实战之银行项目.pdf 尚硅谷 Java 技术之 JDBC.pdf 尚硅谷 Java 技术之 Java ...

  5. 尚硅谷Java高级笔记

    尚硅谷Java高级笔记 idea的使用: 一些小区别: 其他细节参考idea配置pdf 多线程: 基本概念: 多线程的优点: 何时需要多线程: 线程的创建和使用: 创建多线程的第一种方式: /** * ...

  6. Java实现单链表的各种操作

    Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素   4.实现链表的反转   5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...

  7. JAVA 链表操作:单链表和双链表

    主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都 ...

  8. 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

    概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...

  9. 用Java实现单链表的基本操作

    笔试题中经常遇到单链表的考题,下面用java总结一下单链表的基本操作,包括添加删除节点,以及链表转置. package mars; //单链表添加,删除节点 public class ListNode ...

  10. java单链表代码实现

    用惯了C++,java写起来果然不太爽...不废话了,上代码... package javaInnerclassDemo; class Link{ class Node{ private String ...

随机推荐

  1. java基础---设计模式(2)

    结构型模式 出处:https://blog.csdn.net/zhangerqing/article/details/8239539 一.适配器模式 适配器模式将某个类的接口转换成客户端期望的另一个接 ...

  2. NTFS安全权限

    一.NTFS权限概述 1.通过设置NTFS权限,实现不同的用户访问不同的对象的权限 2.分配了真确的访问权限后,用户才能访问其资源 3.设置权限防止资源被篡改.删除 二.文件系统概述 文件系统即在外部 ...

  3. python根据窗口标题找句柄,将窗口前置活动

    import time, threading, copy import win32api, win32con import win32gui import win32gui def zhaojb(aa ...

  4. python import 导入两个模块同时有同一名称的方法如何调用 ?

    from moudule import *(这种方法不推荐) 一般不推荐使用"from 模块 import"这种语法导入指定模块内的所有成员,因为它存在潜在的风险. 比如同时导入 ...

  5. 【LeetCode】27.移除元素

    27.移除元素 知识点:数组:双指针:: 题目描述 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用额外的数组空间,你必须 ...

  6. Beam Search快速理解及代码解析(上)

    Beam Search 简单介绍一下在文本生成任务中常用的解码策略Beam Search(集束搜索). 生成式任务相比普通的分类.tagging等NLP任务会复杂不少.在生成的时候,模型的输出是一个时 ...

  7. jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处

    之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...

  8. U 跳转中加入变量参数的写法

    href="{:U('Message/news?id='.$vo['messageid'].'')}" 就是在U方法里如果参数是变量就用 '.$i.'代替 {$i} <a h ...

  9. 【LeetCode】841. 钥匙和房间

    841. 钥匙和房间 知识点:图:递归 题目描述 有 N 个房间,开始时你位于 0 号房间.每个房间有不同的号码:0,1,2,...,N-1,并且房间里可能有一些钥匙能使你进入下一个房间. 在形式上, ...

  10. 使用递归计算1~n之间所有整数的和

    5+getSum(4) 5+4+getSum(3) 5+4+3+getSum(2) 5+4+3+2+getSum(1) 5+4+3+2+1 function getSum(n){ if(n===1){ ...