天天看点

java链表 作用_链表详解(Java实现)

二、链表

2.1 单链表

2.1.1 概述

功能:遍历打印、添加到最后、按ID大小添加、根据ID进行修改、根据ID删除节点

2.1.2 代码及详细注释

package linkedlist;

import linkedlist.pojo.User;

public class UndirectionalLinkedList {

// 头指针一开始就要初始化

private Node head = new Node();

public void push(User user){

Node node = new Node(user);

Node tmp = head;

while(true){

if(tmp.next == null){

break;

}

// 注意指针后移,防止死循环

tmp = tmp.next;

}

tmp.next = node;

}

public void show(){

Node tmp = head.next;

if (tmp == null) {

System.out.println("链表为空!");

}

while(true){

if(tmp == null){

return;

}

System.out.println(tmp);

tmp = tmp.next;

}

}

public boolean insert(User user) {

Node node = new Node(user);

Node tmp = head;

boolean flag = false; // 默认插入失败

while(true){

if(tmp.next == null){

flag = true;

break;

}

if(node.user.getId() < tmp.next.user.getId()) {

flag = true;

break;

}

if(node.user.getId() == tmp.next.user.getId()) {

break;

}

tmp = tmp.next;

}

if(flag) {

node.next = tmp.next;

tmp.next = node;

}

return flag;

}

public boolean update(User user) {

Node node = new Node(user);

Node tmp = head.next;

boolean flag = false; // 默认更新失败

if(tmp == null){

System.out.println("链表为空!");

return flag;

}

while (true) {

if (tmp == null) {

break;

}

if (node.user.getId() == tmp.user.getId()) {

flag = true;

break;

}

tmp = tmp.next;

}

if(flag){

tmp.user.setName(node.user.getName());

}

return flag;

}

public boolean delete(int id) {

Node tmp = head;

boolean flag = false; // 默认删除失败

if(tmp.next == null) {

System.out.println("链表为空!");

return flag;

}

while(true) {

if(tmp.next == null) {

break;

}

if(tmp.next.user.getId() == id) {

flag = true;

break;

}

tmp = tmp.next;

}

if(flag) {

tmp.next = tmp.next.next;

}

return flag;

}

private class Node {

private User user;

private Node next;

public Node(){}

public Node(User user) {

this.user = user;

}

@Override

public String toString() {

return "Node{" +

"user=" + user +

'}';

}

}

}

2.1.3 代码2.0版(完整版)

注意:完整版对show方法进行了改造,增加了入栈、出栈、单链表的翻转、反向打印、有序合并这5个方法

package linkedlist;

import linkedlist.pojo.User;

public class UndirectionalLinkedList {

// 头指针一开始就要初始化

private Node head = new Node();

public void push(User user){

Node node = new Node(user);

Node tmp = head;

while(true){

if(tmp.next == null){

break;

}

// 注意指针后移,防止死循环

tmp = tmp.next;

}

tmp.next = node;

}

private void _show(Node head){

Node tmp = head.next;

if (tmp == null) {

System.out.println("链表为空!");

}

while(true){

if(tmp == null){

return;

}

System.out.println(tmp);

tmp = tmp.next;

}

}

public void show(){

this._show(this.head);

}

public boolean insert(User user) {

Node node = new Node(user);

Node tmp = head;

boolean flag = false; // 默认插入失败

while(true){

if(tmp.next == null){

flag = true;

break;

}

if(node.user.getId() < tmp.next.user.getId()) {

flag = true;

break;

}

if(node.user.getId() == tmp.next.user.getId()) {

break;

}

tmp = tmp.next;

}

if(flag) {

node.next = tmp.next;

tmp.next = node;

}

return flag;

}

public boolean update(User user) {

Node node = new Node(user);

Node tmp = head.next;

boolean flag = false; // 默认更新失败

if(tmp == null){

System.out.println("链表为空!");

return flag;

}

while (true) {

if (tmp == null) {

break;

}

if (node.user.getId() == tmp.user.getId()) {

flag = true;

break;

}

tmp = tmp.next;

}

if(flag){

tmp.user.setName(node.user.getName());

}

return flag;

}

public boolean delete(int id) {

Node tmp = head;

boolean flag = false; // 默认删除失败

if(tmp.next == null) {

System.out.println("链表为空!");

return flag;

}

while(true) {

if(tmp.next == null) {

break;

}

if(tmp.next.user.getId() == id) {

flag = true;

break;

}

tmp = tmp.next;

}

if(flag) {

tmp.next = tmp.next.next;

}

return flag;

}

private Node _reverse() {

if(head.next == null || head.next.next == null) { // 1个或0个不翻转

return head;

}

Node cur = head.next;

Node reverseHead = new Node();

while (cur != null) {

Node next = cur.next;

cur.next = reverseHead.next;

reverseHead.next = cur;

cur = next;

}

return reverseHead;

}

public void reverse() {

Node node = this._reverse();

head.next = node.next;

}

public void reversePrint() {

if(head.next == null) {

System.out.println("[]");

return;

}

Node node = this._reverse();

_show(node);

}

public void stackPush(User user) {

Node node = new Node(user);

node.next = head.next;

head.next = node;

}

public User stackPop() {

if (head.next == null) {

return null;

}

Node res = head.next;

head.next = res.next;

// 复制user

User user = new User();

user.setName(res.user.getName());

user.setId(res.user.getId());

return user;

}

public UndirectionalLinkedList mergeSorted(UndirectionalLinkedList otherList) {

UndirectionalLinkedList newList = new UndirectionalLinkedList();

if(otherList.head.next == null) {

newList.head.next = this.head.next;

return newList;

}

Node cur = this._reverse().next;

Node otherCur = otherList._reverse().next;

while (cur != null && otherCur != null) {

User user = new User();

if(cur.user.getId() > otherCur.user.getId()) {

user.setId(cur.user.getId());

user.setName(cur.user.getName());

cur = cur.next;

}else{

user.setId(otherCur.user.getId());

user.setName(otherCur.user.getName());

otherCur = otherCur.next;

}

newList.stackPush(user);

}

while (cur != null) {

User user = new User();

user.setId(cur.user.getId());

user.setName(cur.user.getName());

cur = cur.next;

newList.stackPush(user);

}

while (otherCur != null) {

User user = new User();

user.setId(otherCur.user.getId());

user.setName(otherCur.user.getName());

otherCur = otherCur.next;

newList.stackPush(user);

}

return newList;

}

private class Node {

private User user;

private Node next;

public Node(){}

public Node(User user) {

this.user = user;

}

@Override

public String toString() {

return "Node{" +

"user=" + user +

'}';

}

}

}

2.2 双向链表

2.2.1 概述

双向链表,相比于单向链表,既能够找前驱也能够找后驱,本次实现是双向链表的增删改查

2.2.2 代码

UserNode

package linkedlist.node;

import lombok.Data;

@Data

public class UserNode {

private Integer id;

private String name;

private UserNode next;

private UserNode pre;

public UserNode(Integer id, String name) {

this.id = id;

this.name = name;

}

public UserNode() {

}

@Override

public String toString() {

return "UserNode{" +

"id=" + id +

", name='" + name + '\'' +

'}';

}

}

双向链表主体

package linkedlist.dual;

import linkedlist.node.UserNode;

public class DualLinkedList {

// 头结点

private UserNode head = new UserNode();

// 尾结点

private UserNode tail = head;

private int size = 0;

public int getSize() {

return size;

}

public boolean isEmpty() {

return head == tail;

}

public void show() {

if (isEmpty()) {

System.out.println("[]");

return;

}

UserNode cur = head.getNext();

while (cur != null) {

System.out.println(cur);

cur = cur.getNext();

}

}

public void reverseShow() {

if (isEmpty()) {

System.out.println("[]");

return;

}

UserNode cur = tail;

while (cur != head) {

System.out.println(cur);

cur = cur.getPre();

}

}

public void add(UserNode newNode) {

tail.setNext(newNode);

newNode.setPre(tail);

tail = newNode;

size++;

}

public void remove(int id) {

if(isEmpty()) {

System.out.println("链表为空,删除失败");

return;

}

UserNode cur = head.getNext();

boolean flag = false; // flag为false表示没有找到该id对应的结点

while (cur != null) {

if(cur.getId() == id) {

flag =true;

break;

}

cur = cur.getNext();

}

if(flag) {

if(cur == tail) { // 如果要删除最后一个结点,需要特判

tail = tail.getPre();

tail.setNext(null);

size--;

return;

}

cur.getPre().setNext(cur.getNext()); // 当前结点前驱的后驱指向当前结点的后驱

cur.getNext().setPre(cur.getPre()); // 当前结点后驱的前驱指向当前结点的前驱

size--;

}else {

System.out.println("未找到ID="+id+"的结点");

}

}

public void update(UserNode newNode) {

if(isEmpty()) {

System.out.println("链表为空,无法进行更新操作");

return;

}

UserNode cur = head.getNext();

boolean flag = false; // flag为false表示没有找到该id对应的结点

while (cur != null) {

if(cur.getId() == newNode.getId()) {

flag =true;

break;

}

cur = cur.getNext();

}

if(flag) {

cur.setName(newNode.getName());

}else {

System.out.println("未找到待更新结点");

}

}

}

2.3 循环单向链表与约瑟夫问题

2.3.1 概述

循环单向链表一般不设置头结点,删除结点需要把所有条件考虑清楚

约瑟夫问题:

n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 1 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

2.3.2 AC代码

import java.util.Scanner;

public class Main {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

int n = sc.nextInt();

int m = sc.nextInt();

CircleLinkedList circleLinkedList = new CircleLinkedList();

circleLinkedList.exitFromJosepCircle(n,m);

}

}

class CircleLinkedList {

private JosephNode head = null;

private JosephNode tail = null;

private int size = 0;

public int getSize() {

return size;

}

public boolean isEmpty() {

return head == null;

}

public void show() {

if(isEmpty()) {

System.out.println("[]");

return;

}

JosephNode cur = head;

while (true) {

System.out.println(cur);

if (cur == tail) {

break;

}

cur = cur.getNext();

}

}

public void add(JosephNode node) {

if(head == null) {

head = node;

tail = head;

tail.setNext(head);

size++;

return;

}

tail.setNext(node);

tail = node;

tail.setNext(head);

size++;

}

public void clear() {

size = 0;

head = null;

tail = null;

}

public void delete(int id) {

if(isEmpty()) {

System.out.println("该链表为空,不能删除");

return;

}

if(size == 1) { // 如果只有一个结点

clear();

return;

}

if (head.getId() == id && size > 1) { // 如果要删除第一个结点,特判

head = head.getNext();

tail.setNext(head);

size--;

return;

}

JosephNode cur = head;

JosephNode cur4next = head.getNext();

boolean flag = false; // 默认代表没找到结点

while (true) {

if(cur4next.getId() == id) {

flag = true;

break;

}

if(cur4next == tail) {

break;

}

cur = cur.getNext();

cur4next = cur4next.getNext();

}

if(flag) { // 找到了

if(cur4next == tail) {

tail = cur;

}

cur.setNext(cur4next.getNext());

size--;

}else {

System.out.println("不存在待删除的结点");

}

}

public void constructJosepCircle(int n) {

for(int i=1;i<=n;i++) {

JosephNode josephNode = new JosephNode(i);

add(josephNode);

}

}

public void exitFromJosepCircle(int n,int m) {

clear();

constructJosepCircle(n);

JosephNode cur = head;

while (size > 0) {

for(int i=0;i

cur = cur.getNext();

}

System.out.printf("%d ",cur.getId());

delete(cur.getId());

if(size > 0) {

cur = cur.getNext();

}

}

}

}

class JosephNode {

private int id;

private JosephNode next;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public JosephNode getNext() {

return next;

}

public void setNext(JosephNode next) {

this.next = next;

}

@Override

public String toString() {

return "JosephNode{" +

"id=" + id +

'}';

}

public JosephNode(int id) {

this.id = id;

}

public JosephNode() {}

}