Java单链表的实现
- 初级算法学习到了链表的操作…结果发现我连链表是啥都不知道…只能开始学了
单链表很简单,一个对象里存数据然后有个指针指向下一个对象(说的不对大佬纠正我…反正我就这么理解的)
话不多说直接上代码
这个是结点类
public class Node {
public int data;
public Node next;
public Node(){
}
public Node (int data){
this.data = data;
}
}
单链表的增删改查..都写了注释
public class Test {
private Node head;
public Test(){
head = new Node(100); //无参构造自动为0
}
/**
* 添加结点到链表末尾
* @param node
*/
public void addNode(Node node){
Node temp = head; //初始为头结点(是一个移动的指针指向当前遍历的结点)
while (temp.next != null){ //遍历链表
temp = temp.next; //如果当前节点的next不为null.那么temp(移动的指针)就等于当前遍历的结点.直到当前遍历的结点的next为null就跳出循环
}
temp.next = node;
}
/**
* 根据index索引获得数据
* @param index
* @return
*/
public int get(Integer index){
Node temp = head; //初始为头结点(是一个移动的指针指向当前遍历的结点)
int now = 0; //当前遍历的索引
if (index == 0){ //如果索引为0就直接返回头部data
return temp.data;
}
while (temp.next != null){ //遍历
temp = temp.next; //每遍历一次temp就变为该次遍历的结点
now++; //索引+1
if (now == index){ //如果当前索引与index索引相同就返回当前索引数据
return temp.data;
}
}
return -1; //没有该索引就返回-1
}
/**
* 在头结点前添加数据作为新的头结点
* @param node
*/
public void addAtHead(Node node){
Node temp = head; //存储头结点
head = node; //重定义头结点
head.next = temp; //将原头结点添加到下一个
}
/**
* 在链表中的第index个节点之前添加值为node的节点
* 如果index等于链表的长度,则该节点将附加到链表的末尾
* 如果 index 大于链表长度,则不会插入节点
* 如果index小于等于0,则在头部插入节点。
* @param index
* @param node
*/
public void addAtIndex(Integer index,Node node){
if (index <= 0){
addAtHead(node);
}
if (index > length()){
System.out.println("超过链表长度");
}
if (index == length()){
addNode(node);
}
else {
Node temp = head; //初始为头结点(是一个移动的指针指向当前遍历的结点)
int now = 0; //当前遍历的索引
while (temp.next != null){ //遍历
now++; //索引自增
if (index == now){ //如果index索引等于当前索引(此时的指针还未修改)
node.next = temp.next; //node的右指针为上一个结点的右指针
temp.next = node; //上一个结点的右指针指向node
break; //跳出遍历
}
temp = temp.next; //每遍历一次temp就变为该次遍历的结点
}
}
}
/**
* 如果索引index有效,则删除链表中的第index个节点。
* @param index
*/
public void deleteAtIndex(Integer index){
if (index == 0){ //index索引等于0就把头部变为原头部的右指针
head = head.next;
}
Node temp = head;//初始为头结点(是一个移动的指针指向当前遍历的结点)
int now = 0; //当前遍历的索引
if (index >=0 && index <= length()){
while (temp.next != null){ //遍历
now++; //索引自增
if (index == now){ //匹配当前索引
if (index == length()){ //如果index索引是该链表的最后一个就设为null
temp.next = null;
break;
}
temp.next = temp.next.next;
break;
}
temp = temp.next; //每遍历一次temp就变为该次遍历的结点
}
}else { //索引无效
System.out.println("该索引无效");
}
}
/**
* 计算单链表的长度,也就是有多少个结点
* @return 结点个数
*/
public int length() {
int length=0;
Node temp = head;
while(temp.next != null){
length++;
temp = temp.next;
}
return length;
}
/**
* 遍历单链表,打印所有data
*/
public void print(){
Node temp = head.next;
while(temp != null){
System.out.println(temp.data+",");
temp = temp.next;
}
}
}
这就是测试类了
import java.math.BigInteger;
import java.util.ArrayList;
@SuppressWarnings("SpellCheckingInspection")
public class LeetCode {
public static void main(String[] args) {
Test test = new Test();
for (int i = 0; i < 10; i++) {
Node node = new Node(i);
test.addNode(node);
}
/**
* 在头结点前添加并修改为头结点
Node node = new Node(999);
test.addAtHead(node);
*/
/**
* 在链表中的第index个节点之前添加值为node的节点
* 如果index等于链表的长度,则该节点将附加到链表的末尾
* 如果 index 大于链表长度,则不会插入节点
* 如果index小于等于0,则在头部插入节点。
Node node = new Node(2005);
test.addAtIndex(1,node);
*/
/**
* 如果索引index有效,则删除链表中的第index个节点。
test.deleteAtIndex(1);
*/
System.out.println(test.get(0)); //第0个结点返回-1 第1个结点返回0 第2个结点返回1 ......
System.out.println(test.get(1));
System.out.println(test.get(2));
System.out.println(test.get(3));
System.out.println(test.get(4));
System.out.println(test.get(5));
System.out.println(test.get(6));
System.out.println(test.get(7));
System.out.println(test.get(8));
System.out.println(test.get(9));
System.out.println(test.get(10));
System.out.println(test.get(11));
System.out.println(test.length());
}
}
小总结:
- 链表存储不如ArrayList来的方便,而且查询某个索引的时候需要全部去遍历
- 链表的优势在于可以方便的在链表中间插入数据,效率大大高于ArrayList
- 各有各的好叭…