使用Java语言实现单链表的基本操作,包括对单链表的指定节点插入数据、删除指定位置节点的数据、修改指定节点的数据,查询数据;以及单链表的反转和倒数第k个节点的输出。
线性表的链式存储结构:n个结点链结成一个链表,即为线性表的链式存储结构,由于每一个结点只包含一个指针域,因此称为单链表。
链表中第一个结点的存储位置成为头指针,那么整个链表的存取就必须是从头指针开始了。有时候会在单链表的第一个结点前附设一个结点,称为头结点。
简单节点类,存储数据:Node.java
public class Node {
int value; //数据域
Node next; //指针域
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
模拟单链表类:SingleList.java
//单链表
public class SingleList {
//头结点
public Node head;
//获取链表的长度的方法
public int getLength() {
int length = 0;
Node cur = head;
while (cur != null) {
cur = cur.next;
length++;
}
return length;
}
// 头插法,添加结点至链表头部
public void addHeadNode(int value) {
Node newNode = new Node(value);
//头结点不存在,新结点成为头结点
if (head == null) {
head = newNode;
return;
}
//新结点next直接指向当前头结点
newNode.next = head;
//新结点成为新的头结点
head = newNode;
}
// 尾插法,添加结点至链表尾部
public void addTailNode(int value) {
Node newNode = new Node(value);
//头结点不存在,新结点成为头结点
if (head == null) {
head = newNode;
return;
}
//找到最后一个结点
Node last = head;
while (last.next != null) {
last = last.next;
}
//新结点插入到链表尾部
last.next = newNode;
}
// 结点插入至指定位置
public void addByIndex(int value, int index) {
if (index < 0 || index > getLength()) { //注意index是可以等于size()的
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
if (index == 0) { //插入到头部
addHeadNode(value);
} else if (index == getLength()) { //插入到尾部
addTailNode(value);
} else { //插到某个中间位置
Node newNode = new Node(value);
int position = 0;
Node cur = head; //标记当前结点
Node pre = null; //记录前置结点
while (cur != null) {
if (position == index) {
newNode.next = cur;
pre.next = newNode;
return;
}
pre = cur;
cur = cur.next;
position++;
}
}
}
// 删除指定位置的结点
public void deleteByIndex(int index) {
if (index < 0 || index > getLength() - 1) {
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
if (index == 0) { //删除头
head = head.next;
return;
}
int position = 0; //记录当前位置
Node cur = head; //标记当前结点
Node pre = null; //记录前置结点
while (cur != null) {
if (position == index) {
pre.next = cur.next;
cur.next = null; //断开cur与链表的连接
return;
}
pre = cur;
cur = cur.next;
position++;
}
}
//修改操作
public void update(int value, int index) {
if (index < 0 || index > getLength() - 1) {
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
int position = 0;
Node cur = head;
while (cur != null) {
if (position == index) {
cur.value = value;
}
cur = cur.next;
position++;
}
}
//遍历链表
public void show() {
Node cur = head;
while (cur != null) {
System.out.println(cur);
cur = cur.next;
}
}
// 链表反转
public void reverse() {
Node cur = head; //标记当前结点
Node pre = null; //标记当前结点的前一个结点
Node temp;
while (cur != null) {
//保存当前结点的下一个结点
temp = cur.next;
//cur.next指向pre,指针顺序置换
cur.next = pre;
//pre、cur继续后移
pre = cur;
cur = temp;
}
//最后一个结点变成新的头结点
head = pre;
}
// 输出倒数第k个结点【新浪面试题】
public Node getLastK(int k) {
if (k < 0 || k > getLength()) {
throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
}
Node cur = head;
for (int i = 1; i < getLength() - k + 1; i++) {
cur = cur.next;
}
return cur;
}
}
测试方法
public static void main(String[] args) {
SingleList list = new SingleList();
list.addHeadNode(3);
list.addHeadNode(2);
list.addHeadNode(1);
list.addTailNode(7);
list.addTailNode(9);
list.addByIndex(5, 1);
list.show();
System.out.println("倒数第2个节点:" + list.getLastK(2));
System.out.println("-----------------------");
//删除
list.deleteByIndex(4);
list.reverse();//翻转
list.update(100, 1);
list.show();
}