链表(单向)
基本介绍
链表是有序列表,但是在内存中是存储如下。
如上图:
1)链表是以节点的方式来存储,是链式存储。
2)每个节点包含data域,next域:指向下一个节点。
3)链表的各个节点不一定是连续存储。
4)链表分带头节点的链表和没有头节点的链表。
单链表(带头节点)逻辑结构示意图如下
增删改查
节点类
package com.linkedlist.test;
public class Node {
public int no;
public String name;
public Node next;
public Node(int no,String name){
this.no = no;
this.name = name;
}
public Node(){};
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name +
'}';
}
}
增
方法一:
先创建一个head头节点。
后面每添加一个节点,就直接加入到链表的最后。
通过一个辅助节点变量,帮助遍历整个链表。
public void add(Node node){
Node temp = head;
while(true){
if(temp.next == null){
break;
}
temp = temp.next;
}
temp.next = node;
}
方法二:
根据编号的顺序添加:
首先找到新添加节点的位置,通过辅助节点完成添加
public void addOrderByAsc(Node node){
Node 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.println("节点已经存在!");
}else{
node.next = temp.next;
temp.next = node;
}
}
删
先找到需要删除节点的前一个节点temp;
temp.next = temp.next.next;
被删除的节点,将不会有其他引用指向,会被垃圾回收机制回收;
public void del(int no){
boolean flag = false;
Node temp = head;
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.println("未找到该节点!");
}
}
改
通过遍历找到要修改的节点进行修改
public void update(Node node){
if(head.next == null){
System.out.println("链表为空!");
return;
}
boolean flag = false;
Node temp = head.next;
while(true){
if(temp == null){
break;
}
if(temp.no == node.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.name = node.name;
}else{
System.out.println("未找到该节点!");
}
}
其他操作
- 获取链表有效节点个数。
public int getLength(){
int length = 0;
Node temp = head;
while(true){
if(temp.next == null){
break;
}
length++;
temp = temp.next;
}
return length;
}
- 获取倒数第n个节点
public Node getLastNode(int n){
if( n <= 0 || n > getLength()){
return null;
}
Node temp = head.next;
for (int i = 0; i < getLength() - n; i++) {
temp = temp.next;
}
return temp;
}
- 反转链表
public void reverseLinkedList(){
if(head.next == null || head.next.next == null){
return;
}
Node cur = head.next;
Node next = null; //指向当前节点的下一个节点
Node reverseHead = new Node();
//遍历原来的链表,每遍历一个节点,就将其取出放在reverseHead的最前端
while(cur != null){
next = cur.next; //暂时保存当前节点的下一个节点
cur.next = reverseHead.next; //将cur的下一个节点指向新的链表的最前端
reverseHead.next = cur; //将cur连接到新链表上
cur = next; //后移
}
head.next = reverseHead.next;
}
- 逆序打印
public void reversePrint(){
Stack<Node> stack = new Stack<Node>();
Node cur = head.next;
while(cur != null){
stack.push(cur);
cur = cur.next;
}
while(stack.size() > 0){
System.out.println(stack.pop());
}
}