编程导航算法通关村第一关|1. 链表基础,链表的创建以及增删改查
1. 什么是链表
链表是一种线性的数据结构,组成链表的基本结构称为节点,每个节点由 ”数据 + 下一节点的指针“ 组成。
在Java中我们是这样去定义一个节点的
public class Node {
//这里将类的参数定义成public只是为了方便访问,
public int data;
public Node next;
public Node() {
}
public Node(int data) {
this.data = data;
}
}
关于单链表:
- 不管进行什么操作,一定是从头开始逐个向后访问,所以管理好链表的表头(第一个节点)很重要。
2. 链表的基本操作
为了更好的了解链表,我们从0创建一个链表,并对他进行基本的操作。
public static void main(String[] args) {
//测试头插入
Node head = new Node(2);
Node node_1 = new Node(1);
head = insertNode(head, node_1, 1);
printlnNodeData(head);
//测试尾插入
Node node_2 = new Node(4);
head = insertNode(head, node_2, 3);
printlnNodeData(head);
//中间插入
Node node_3 = new Node(3);
head = insertNode(head, node_3, 2);
printlnNodeData(head);
//中间插入
Node node_4 = new Node(5);
head = insertNode(head, node_4, 2);
printlnNodeData(head);
//删除头节点
head = delNode(head, 1);
printlnNodeData(head);
//删除尾巴节点
head = delNode(head, 4);
printlnNodeData(head);
//删除中间节点
head = delNode(head, 2);
printlnNodeData(head);
}
/*
* 遍历链表,获得链表长度
* */
public static int getListLength(Node head){
int length = 0;
Node node = head;
while (node != null){
length++;
node = node.next;
}
return length;
}
/*
* 遍历输出节点上的数据
* */
public static void printlnNodeData(Node head){
Node node = head;
while (node != null){
System.out.print(node.data + " ");
node = node.next;
}
System.out.println("");
}
/*
* 获得任意位置节点
* */
public static Node getNodeByIndex(Node head, int index){
int size = getListLength(head);
if (index > size || index < 0){
throw new IndexOutOfBoundsException("index out!");
}
Node temp = head;
for (int i = 1; i < index; i++) {
temp = temp.next;
}
return temp;
}
/*
* 链表插入节点
* @author hhy
* @param head 头节点
* @param nodeInsert 待插入节点
* @param index 节点位置,1开始
* */
public static Node insertNode(Node head, Node nodeInsert, int index){
if (head == null) {
throw new RuntimeException(" headNode is null error !");
}
int size = getListLength(head);
if (index > size + 1 || index < 1){
throw new IndexOutOfBoundsException("index out!");
}
//头插入
if (index == 1){
nodeInsert.next = head;
return nodeInsert;
}
//尾巴插入
/*if (index == size + 1){
Node last = getNodeByIndex(head, index - 1);//获取尾节点
last.next = nodeInsert;
return head;
}*/
//中间插入
Node last = getNodeByIndex(head, index - 1);//拿到需要插入的位置的上一个节点
//这里的操作的顺序不能变
nodeInsert.next = last.next;
last.next = nodeInsert;
return head;
}
/*
* 链表删除节点
* @author hhy
* @param head 头节点
* @param index 节点位置,1开始
* */
public static Node delNode(Node head, int index){
if (head == null) {
throw new RuntimeException(" headNode is null error !");
}
int size = getListLength(head);
// index这里不像插入的时候可以为 size+1, size+1 上没有节点,删除需要在有节点的情况下才有意义
if (index > size || index < 1){
throw new IndexOutOfBoundsException("index out!");
}
//删除头节点
if (index == 1){
return head.next;
}
//删除尾节点
if (index == size){
Node last = getNodeByIndex(head, index - 1);//获取倒数第二个节点
last.next = null;
return head;
}
//删除中间节点
Node last = getNodeByIndex(head, index - 1);//获取上一个节点
last.next = last.next.next;
return head;
}
测试结果
1 2
1 2 4
1 3 2 4
1 5 3 2 4
5 3 2 4
5 3 2
5 2