使用Java实现链表的基本操作时,不像C++有那么明显的申请空间和释放空间的语句。在申请空间时,Java使用new关键字;在释放空间时,因为Java使用自动垃圾回收机制,所以一般就是将要释放的结点的引用都置为空。
链表中的各元素称之为结点。结点使用类来实现,比如双向链表中的结点包括数据本身,指向前一元素的指针以及指向后一元素的指针。
有时,有的链表还有一个头结点,这个结点可以简化链表的实现。
以AOJ(Aizu Online Judge)中的一题双向循环链表为例进行说明。题目链接 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_C
Your task is to implement a double linked list.
Write a program which performs the following operations:
- insert x: insert an element with key x into the front of the list.
- delete x: delete the first element which has the key of x from the list. If there is not such element, you need not do anything.
- deleteFirst: delete the first element from the list.
- deleteLast: delete the last element from the list.
Input
The input is given in the following format:
n
command1
command2
...
commandn
In the first line, the number of operations n is given. In the following n lines, the above mentioned operations are given in the following format:
- insert x
- delete x
- deleteFirst
- deleteLast
Output
Print all the element (key) in the list after the given operations. Two consequtive keys should be separated by a single space.
Constraints
- The number of operations ≤ 2,000,000
- The number of delete operations ≤ 20
- 0 ≤ value of a key ≤ \(10^9\)
- The number of elements in the list does not exceed \(10^6\)
- For a delete, deleteFirst or deleteLast operation, there is at least one element in the list.
Sample Input 1
7
insert 5
insert 2
insert 3
insert 1
delete 3
insert 6
delete 5
Sample Output 1
6 1 2
Sample Input 2
9
insert 5
insert 2
insert 3
insert 1
delete 3
insert 6
delete 5
deleteFirst
deleteLast
Sample Output 2
1
题目大意是输入\(n\)个命令,命令有四种形式。所有命令执行完毕后,输出链表的键值。
参考代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// 定义双向循环链表的结点
class Node{
int value;
Node prev;
Node next;
Node(){
}
Node(int value){
this.value = value;
}
}
public class Main {
static Node head;
// 初始化链表,这是一个循环链表
private static void init(){
head = new Node();
head.next = head;
head.prev = head;
}
// 在链表开头添加结点
public static void insert(int x){
Node temp = new Node(x);
temp.next = head.next;
temp.prev = head;
head.next = temp;
temp.next.prev = temp;
}
//使用两个方法来实现delete,首先是寻找到结点,然后再删除
public static void delete(int x){
deleteNode(listSearch(x));
}
public static Node listSearch(int x){
Node cur = head.next;
while (cur != head && cur.value != x){
cur = cur.next;
}
return cur; // 此处没有考虑找不到的情况,题目说至少有一个元素存在链表中
}
public static void deleteNode(Node node){
if (node == head){
return;
}
node.prev.next = node.next;
node.next.prev = node.prev;
// 将node的引用都置为null,以便可以尽快回收
node.prev = null;
node.next = null;
}
public static void deleteFirst(){
deleteNode(head.next);
}
public static void deleteLast(){
deleteNode(head.prev);
}
// 打印链表元素,需要注意空格和换行的问题
private static void printList() {
int count = 0;
Node cur = head.next;
while (cur != head){
if (count++ > 0){
System.out.print(" ");
}
System.out.print(cur.value);
cur = cur.next;
}
// 最后如果不换行的话会报格式错误的问题
System.out.println();
}
public static void main(String[] args) throws IOException {
init();
// Scanner sc = new Scanner(System.in);
// int n = sc.nextInt();
//
// for (int i=0; i<n; i++){
// String str = sc.next();
// // equals会超时
// if (str.charAt(0) == 'i'){
// int key = sc.nextInt();
// insert(key);
// }else if (str.length() > 6){
// if (str.charAt(6) == 'F') {
// deleteFirst();
// }else {
// deleteLast();
// }
// } else {
// int key = sc.nextInt();
// delete(key);
// }
// }
// 使用Scanner时,一直超时,换成下面的就不超时了
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for (int i=0; i<n; i++){
String str = br.readLine();
if (str.charAt(0) == 'i'){
int key = Integer.parseInt(str.substring(7));
insert(key);
} else if (str.charAt(6) == 'F'){
deleteFirst();
} else if (str.charAt(6) == 'L'){
deleteLast();
} else {
int key = Integer.parseInt(str.substring(7));
delete(key);
}
}
printList();
}
}