5.单向链表
把一个节点Node当做是一个对象,改对象里面包含了数据和指向下一个节点的引用指针
5.1 链表的添加和遍历
5.1.1 思路分析
- 添加
- 创建一个head头节点表示链表的头节点,里面的存放数据的data = null
- 每添加一个元素就直接添加到链表的最后(尾插法)
- 遍历
List、LinkedHashMap、LinkedHashSet、TreeMap、TreeSet是有序的,List、LinkedHashMap、LinkedHashSet、LinkedHashSet 在遍历时会保持添加的顺序,TreeMap、TreeSet 在遍历时会以自然顺序(Comparable接口的compareTo )输出
5.1.2 代码实现
package com.tomdd.model;
public class SingleHeroNode {
public Integer no;
public String name;
public String nickName;
public SingleHeroNode next;
public SingleHeroNode(Integer 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 + '\'' +
'}';
}
}
package com.tomdd.linkedlist;
import com.tomdd.model.SingleHeroNode;
/**
* 英雄单向链表
*
* @author zx
* @date 2022年12月21日 10:32
*/
public class HeroSingleLinkedList {
/**
* 初始化一个头结点(头结点不能动)
*/
private SingleHeroNode head = new SingleHeroNode(0, null, null);
/**
* 添加结点数据到单向链表
*/
public void add(SingleHeroNode singleHeroNode) { //尾插发
//思路:找到结点最后一个结点数据,然后把新增的数据放到结点末尾即可 [不考虑编号顺序]
//找到末尾结点;然后末尾结点的next域指向新增结点
//1.定义临时结点
SingleHeroNode temp = head;
//2.遍历链表找到最后
while (true) {
if (temp.next == null) {
break;
}
//temp 往后移
temp = temp.next;
}
temp.next = singleHeroNode;
}
/**
* <h2>遍历链表</h2>
* 需要辅助遍历.head结点不能动的。
*/
public void list() {
//1.链表是否为空
if (head.next == null) {
return;
}
SingleHeroNode temp = head.next;
while (true) {
if (temp == null) {
return;
}
System.out.println(temp);
temp = temp.next;
}
}
}
5.2 按照英雄编号进行顺序添加
5.2.1 思路分析
- 这里添加的位置是他真正添加的位置的前一个节点,找到这个这个节点后可以直接使用
temp.next = newNode; newNode.next = temp.next
5.2.2 代码实现
public void addByOrder(SingleHeroNode singleHeroNode) throws Exception {
SingleHeroNode temp = head;
Boolean flag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > singleHeroNode.no) {
break;
}
if (temp.next.no == singleHeroNode.no) {
flag = true;
}
temp = temp.next;
}
if (flag) {
throw new IllegalAccessException("英雄编号:" + singleHeroNode.no + "已经存在");
}
singleHeroNode.next = temp.next;
temp.next = singleHeroNode;
}
5.3 链表的修改和删除
5.3.1 思路分析
- 修改
- 通过遍历找到需要修改的节点
- 找到该节点后直接修改节点里面的数据内容
- 删除
- 找到该需要删除节点的前面一个节点 ,比如:temp
- 改指针引用:
temp.next = temp.next.next 即可
5.3.2 代码实现
public void updateNodeByNo(SingleHeroNode singleHeroNode) throws Exception {
if (head.next == null) {
throw new IllegalAccessException("节点链表为空");
}
SingleHeroNode temp = head.next;
Boolean flag = false;
while (true) {
if (temp == null) {
break;
}
if (temp.no == singleHeroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.name = singleHeroNode.name;
temp.nickName = singleHeroNode.nickName;
}
if (!flag) {
throw new IllegalAccessException("没有找到编号:" + singleHeroNode.no + "节点信息");
}
}
public void delNode(SingleHeroNode singleHeroNode) throws Exception {
SingleHeroNode temp = head;
Boolean flag = false;
for (; ; ) {
if (temp.next == null) {
break;
}
if (temp.next.no == singleHeroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
}
if (!flag) {
throw new IllegalAccessException("节点编号:" + singleHeroNode.no + "不存在");
}
}
5.4 完整的代码
package com.tomdd.linkedlist;
import com.tomdd.model.SingleHeroNode;
import java.util.Stack;
@SuppressWarnings("all")
public class SingleLinkedList {
private SingleHeroNode head = new SingleHeroNode(0, null, null);
public void add(SingleHeroNode singleHeroNode) {
SingleHeroNode temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = singleHeroNode;
}
public void addByOrder(SingleHeroNode singleHeroNode) throws Exception {
SingleHeroNode temp = head;
Boolean flag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > singleHeroNode.no) {
break;
}
if (temp.next.no == singleHeroNode.no) {
flag = true;
}
temp = temp.next;
}
if (flag) {
throw new IllegalAccessException("英雄编号:" + singleHeroNode.no + "已经存在");
}
singleHeroNode.next = temp.next;
temp.next = singleHeroNode;
}
public void delNode(SingleHeroNode singleHeroNode) throws Exception {
SingleHeroNode temp = head;
Boolean flag = false;
for (; ; ) {
if (temp.next == null) {
break;
}
if (temp.next.no == singleHeroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
}
if (!flag) {
throw new IllegalAccessException("节点编号:" + singleHeroNode.no + "不存在");
}
}
public void updateNodeByNo(SingleHeroNode singleHeroNode) throws Exception {
if (head.next == null) {
throw new IllegalAccessException("节点链表为空");
}
SingleHeroNode temp = head.next;
Boolean flag = false;
while (true) {
if (temp == null) {
break;
}
if (temp.no == singleHeroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.name = singleHeroNode.name;
temp.nickName = singleHeroNode.nickName;
}
if (!flag) {
throw new IllegalAccessException("没有找到编号:" + singleHeroNode.no + "节点信息");
}
}
public void list() {
if (head.next == null) {
return;
}
SingleHeroNode temp = head.next;
while (true) {
if (temp == null) {
return;
}
System.out.println(temp);
temp = temp.next;
}
}
public synchronized int size() {
if (head.next == null) {
return 0;
}
int size = 0;
SingleHeroNode currentNode = head.next;
while (currentNode != null) {
size++;
currentNode = currentNode.next;
}
return size;
}
public SingleHeroNode getLastIndexNode(int index) {
int size = size();
if (size == 0) {
return null;
}
if (index <= 0 || index > size) {
return null;
}
SingleHeroNode temp = head.next;
for (int i = 0; i < (size - index); i++) {
temp = temp.next;
}
return temp;
}
public void reverse() {
if (head.next == null || head.next.next == null) {
return;
}
SingleHeroNode curr = head.next;
SingleHeroNode currNext = null;
SingleHeroNode reverseHead = new SingleHeroNode(0, null, null);
while (curr != null) {
currNext = curr.next;
curr.next = reverseHead.next;
reverseHead.next = curr;
curr = currNext;
}
head.next = reverseHead.next;
}
public void reversePrintByStack(){
if(head.next == null){
return;
}
Stack<SingleHeroNode> singleHeroNodeStack = new Stack<>();
SingleHeroNode temp = head.next;
while(temp !=null){
singleHeroNodeStack.push(temp);
temp = temp.next;
}
while(singleHeroNodeStack.size()>0){
System.out.println(singleHeroNodeStack.pop());
}
}
}
6.双向链表
package com.tomdd.model;
public class DoubleHeroNode {
public Integer no;
public String name;
public String nickName;
public DoubleHeroNode next;
public DoubleHeroNode pre;
public DoubleHeroNode(Integer 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 + '\'' +
'}';
}
}
package com.tomdd.linkedlist;
import com.tomdd.model.DoubleHeroNode;
public class DoubleLinkedList {
private final DoubleHeroNode head = new DoubleHeroNode(0, null, null);
public void add(DoubleHeroNode newHeroNode) {
if (head.next == null) {
head.next = newHeroNode;
newHeroNode.pre = head;
return;
}
DoubleHeroNode temp = head.next;
while (temp !=null) {
temp = temp.next;
}
temp.next = newHeroNode;
newHeroNode.pre = temp;
}
public void list() {
if (head.next == null) {
return;
}
DoubleHeroNode temp = head.next;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
}
7.使用for循环遍历链表另一种形式
package com.mayikt.linkedlist;
public class SingleLinkedList<T> {
transient Node<T> firstNode;
int size = 0;
public boolean add(T t) {
addNodeToHead(t);
return true;
}
private void addNodeToHead(T t) {
Node<T> tempNode = firstNode;
firstNode = new Node<>(t, tempNode);
size++;
}
public void showInfo() {
Node<T> temp = firstNode;
while (true) {
System.out.println(temp.item);
if (temp.nextEntry == null) {
break;
}
temp = temp.nextEntry;
}
}
public void foreEach() {
for (Node<T> temp = firstNode; temp != null; temp = temp.nextEntry) {
System.out.println(temp.item);
}
}
static class Node<T> {
T item;
Node<T> nextEntry;
public Node(T item, Node<T> nextEntry) {
this.item = item;
this.nextEntry = nextEntry;
}
}
public static void main(String[] args) {
SingleLinkedList<String> singleLinkedList = new SingleLinkedList<>();
singleLinkedList.add("I");
singleLinkedList.add("LOVE");
singleLinkedList.add("YOU");
singleLinkedList.showInfo();
System.out.println("--------------使用for循环遍历链表:------------------");
singleLinkedList.foreEach();
}
}
8.环形链表
8.1 思路分析
8.2 代码实现
package com.mayikt.circle_linked;
public class CircleLinked {
private Body first = new Body(-1);
public void buildCircleLinked(int num) {
if (num < 1) {
throw new RuntimeException("节点数应该大于1");
}
Body currentBody = null;
for (int i = 1; i <= num; i++) {
Body body = new Body(i);
if (i == 1) {
first = body;
first.setNext(first);
currentBody = first;
continue;
}
currentBody.setNext(body);
body.setNext(first);
currentBody = body;
}
}
public void printCircleLinked() {
if (first.getNo() == -1) {
throw new RuntimeException("环形链表为空");
}
Body currentBody = first;
while (true) {
System.out.println(currentBody.getNo());
currentBody = currentBody.getNext();
if (currentBody.getNext() == first) {
System.out.println(currentBody.getNo());
break;
}
}
}
static class Body {
private Integer no;
private Body next;
public Body(Integer no) {
this.no = no;
}
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
public Body getNext() {
return next;
}
public void setNext(Body next) {
this.next = next;
}
}
}
|