Java 手写单向链表
SingleLinkedList.java
package com.muxiaofei.veryday.entity;
/**
* 单链表
* @param <T>
*/
public class SingleLinkedList<T> {
//链表大小
public int size;
// 头节点(先初始化一下)
public Node<T> head = new Node<>();
// 尾巴节点 (刚开始指向头节点)
public Node<T> rear = head;
//数据节点类
private class Node<T>{
//data 存储数据
T data;
//存储下一个节点的引用指针
Node<T> next;
public Node(T data){
this.data = data;
this.next = null;
}
public Node() {
}
@Override
public String toString() {
return "Node{" +
"date=" + data +
'}';
}
}
/**
* 从尾部添加数据
* @param data
*/
public void addRear(T data){
// 根据添加的内容 创建一个节点,next域为null
Node<T> newNode = new Node<>(data);
// 尾节点的next指向新节点
rear.next = newNode;
// 将新节点设置为尾巴节点
rear = newNode;
// 链表大小+1
++size;
}
/**
* 从头部添加数据
* @param data
*/
public void addHead(T data){
// 根据添加的内容 创建一个节点,next域为null
Node<T> newNode = new Node<>(data);
// 新节点的next指向头节点
newNode.next = head.next;
// 将新节点设置为头部节点
head.next = newNode;
// 链表大小+1
++size;
}
/**
* 指定位置添加数据
* @param date 新节点的数据
* @param index 插入的位置
*/
public void insert(T date, int index){
// 判断边界 看看是否越界
if (isValid(index)){
System.out.println("下标超出链表大小");
return;
}
// 获取上一个节点
Node temp = getBefore(index);
// 根据添加的内容 创建一个节点,next域为null
Node<T> newNode = new Node<>(date);
// 准备插入节点
// 新节点获取上一个节点指向下一个节点的数据
newNode.next = temp.next;
// 上一个节点指向新节点
temp.next = newNode;
// 链表长度+1
++size;
}
/**
* 删除指定位置节点
* @param index 指定位置节点
*/
public void delete(int index){
// 判断边界 看看是否越界
if (isValid(index)){
System.out.println("下标超出链表大小");
return;
}
// 获取上一个节点
Node temp = getBefore(index);
// 获取删除位置的下一个节点的坐标
temp.next = temp.next.next;
// 如果删除的是最后的节点
if (index == size){
// 将倒数第二个节点设置为尾节点
rear = temp;
}
// 链表-1
--size;
}
/**
* 修改办法
* @param date 数据类型
* @param index 修改指定内容
*/
public void update(T date, int index){
// 判断边界 看看是否越界
if (isValid(index)){
System.out.println("下标超出链表大小");
return;
}
// 获取当前节点
Node temp = getCurrent(index);
// 修改
temp.data = date;
}
/**
* 遍历节点
*/
public void showList(){
// 判断边界
if (size == 0){
System.out.println("链表长度为0");
return;
}
// head不能动,因此这里要添加一个临时指针
Node temp = head;
while (true){
if (temp == null){
break;
}
System.out.println(temp);
// 这里很重要,临时节点向后移
temp = temp.next;
}
}
/**
* 根据下表获取节点数据
* @param index
* @return
*/
public Object get(int index){
// 判断边界 看看是否越界
if (isValid(index)){
System.out.println("下标超出链表大小");
return null;
}
// 获取当前节点的数据
return getCurrent(index).data;
}
/**
* 反转链表
*/
public void reverse(){
// 判断边界
if (size == 0){
System.out.println("链表长度为0");
return;
}
Node temp = this.head.next;
SingleLinkedList newList = new SingleLinkedList();
while (true){
if (temp == null){
break;
}
// 将当前节点利用 头插法 添加到临时链表中 (头插法是关键)
newList.addHead(temp);
// 遍历所有的节点
temp = temp.next;
}
// 最后把临时链表的head索引复制给当前链表的head
this.head = newList.head;
}
/**
* 判断下标是否有效
* @param index
* @return
*/
public boolean isValid(int index){
if (index > size || index < 0){
return true;
}
return false;
}
/**
* 获取前面一个的节点
* @param index
* @return
*/
public Node<T> getBefore(int index){
// 获取头部节点
Node temp = head;
// 找到删除位置的前一个节点,因此是index-1 因为这是单向链表 不能指向前一个节点
for (int i = 1; i <= index - 1; i++) {
temp = temp.next;
}
return temp;
}
/**
* 获取当前节点
* @param index
* @return
*/
public Node<T> getCurrent(int index){
// 获取头部节点
Node temp = head;
// 找到删除位置的前一个节点,因此是index-1 因为这是单向链表 不能指向前一个节点
for (int i = 1; i <= index; i++) {
temp = temp.next;
}
return temp;
}
}
测试类
SingleLinkedListDemo1.java
package com.muxiaofei.veryday.demo;
import com.muxiaofei.veryday.entity.SingleLinkedList;
/**
* 测试单向链表
*/
public class SingleLinkedListDemo1 {
public static void main(String[] args) {
SingleLinkedList<String> myList = new SingleLinkedList<>();
myList.addRear("字节跳动");
myList.addRear("阿里");
myList.addRear("腾讯");
myList.addRear("美团");
myList.showList();
System.out.println("链表的大小:" + myList.size);
myList.insert("华为", 4);
myList.showList();
System.out.println("链表的大小:" + myList.size);
myList.update("百度", 5);
myList.showList();
System.out.println("链表的大小:" + myList.size);
myList.delete(3);
myList.showList();
System.out.println("链表的大小:" + myList.size);
System.out.println(myList.get(1));
myList.addHead("上官婉儿");
myList.addHead("橘右京");
myList.addHead("廉颇");
myList.showList();
System.out.println("链表的大小:" + myList.size);
}
}
测试类2
SingleLinkedListDemo2.java
package com.muxiaofei.veryday.demo;
import com.muxiaofei.veryday.entity.SingleLinkedList;
/**
* 反转链表
*/
public class SingleLinkedListDemo2 {
public static void main(String[] args) {
SingleLinkedList myList = new SingleLinkedList();
myList.addRear("华为");
myList.addRear("字节跳动");
myList.addRear("百度");
myList.addRear("腾讯");
myList.showList();
// 反转
myList.reverse();
myList.showList();
}
}