单链表的就地逆置是指辅助空间O(1)的逆置方法,使用头插法。
定义单链表的基本操作
package Link;
class Node{ // 定义单链表借点类
public int value; // 该结点所保存的值
public Node next; // da该结点下一个结点指针
public Node(int data){
value = data;
next = null;
}
public Node(){
next =null;
}
}
// 定义单链表基本操作
public class LinkList{
Node head = null; // 头结点为空
// 尾插法创建单链表
public Node TailCreateLinkList(int[] arr){
int len = arr.length;
if(len == 0){
System.out.println("创建空链表");
return head;
}
head = new Node(arr[0]);
Node pre = head;
for(int i = 1;i < len;i++){
Node node = new Node(arr[i]);
pre.next = node;
pre = node;
}
return head;
}
// 头插法创建单链表
public Node HeadCreateLinkList(int[] arr){
int len = arr.length;
if(len == 0){
System.out.println("创建空链表");
return head;
}
for(int i = 0;i < len;i++){
Node node = new Node(arr[i]);
node.next = head; // 在链表头部插入结点
head = node; // 每一个新插入的结点都成为新的头结点
}
return head;
}
// 头插法向链表表头插入一个值
public Node HeadInsertLinkList(int a,LinkList linkList){
if(linkList.head == null){
System.out.println("创建空链表");
head = new Node(a);
return head;
}
Node node = new Node(a);
node.next = head; // 在链表头部插入结点
head = node; // 每一个新插入的结点都成为新的头结点
return head;
}
public void PrintLinkList(Node head){
if(head == null){
System.out.println("链表为空!");
return;
}
Node pre = head;
while (pre != null){
System.out.print(pre.value + "\t");
pre = pre.next;
}
}
public int LinkLength(Node head){
int len = 0;
if(head== null){
System.out.println("链表为空");
return 0;
}
while(head != null){
len++;
head = head.next;
}
return len;
}
public Node LinkListInverse(Node head){
if(head == null){
System.out.println("空链表!");
return head;
}
//注释掉的这段第一个结点处理的复杂了
// Node p = head.next;
// Node q = p.next;
//
// if(q == null){
//
// System.out.println("链表只有一个值,不用翻转!");
// return head;
// }
//
// while(q != null){
//
// p.next = q.next;
// q.next = head.next;
// head.next = q;
//
// q = p.next;
// }
//
// //因为刚才利用原来链表的第一个结点之前插入结点,没做处理该结点,所以最后处理一下第一个结点
// q = head.next;
// p.next = head;
// head = q;
// p.next.next =null;
Node p = head;
Node q = p.next;
if(q == null){
System.out.println("链表只有一个值,不用翻转!");
return head;
}
while(q != null){
p.next = q.next;
q.next = head;
head = q;
q = p.next;
// PrintLinkList(head); // 打印链表
// System.out.println();
}
return head;
}
public Node DeleteElements(int a,Node head){
if(head == null){
System.out.println("空链表!");
return head;
}
while(head.value == a){ // 头结点的值等于待删除的值,单独处理
head = head.next;
if(head == null){
return head;
}
}
Node pre = head; // 指向当前结点的前一结点
Node q = pre.next;
while(q != null){
if(q.value == a){ // 当前结点值恰好为待删除的值,pre指针不用移动,因为删除一个q结点之后会带来一个新的q结点
pre.next = q.next;
q = pre.next;
}
else{ // 当前值不等于待删除值,当前结点指针后移
pre = pre.next;
q = pre.next;
}
}
return head;
}
}
主函数
package Link;
public class LinkListInverse {
public static void main(String[] args) {
int [] arr = new int[] {3,3,3,1,3,4,3,3,3,7,3,0,8,2,3,3,3};
// int [] arr = new int[] {3,3,3,3,3,3,3,3,3,3,3};
LinkList linkList = new LinkList();
System.out.println();
System.out.println("--------尾插法创建单链表--------");
System.out.println();
Node tail = linkList.TailCreateLinkList(arr); // 尾插法创建新结点,tail是头结点指针
linkList.PrintLinkList(tail);
System.out.println();
// LinkList linkListHead = new LinkList();
// Node head = linkListHead.HeadCreateLinkList(arr); // 头插法创建新结点
// linkListHead.PrintLinkList(head);
// System.out.println(linkList.LinkLength(tail)); // 链表长度
System.out.println("--------单链表反转--------");
tail = linkList.LinkListInverse(tail); // 表头改变了,要赋值给一个变量,不然就错了
linkList.PrintLinkList(tail);
// linkList.PrintLinkList(tail); // 为什么链表逆置之后不赋值给tail,tail只有一个值了?
System.out.println();
System.out.println("--------删除所有给定值--------");
System.out.println();
tail = linkList.DeleteElements(3,tail);
linkList.PrintLinkList(tail);
}
}
输出
--------尾插法创建单链表--------
3 3 3 1 3 4 3 3 3 7 3 0 8 2 3 3 3
--------单链表反转--------
3 3 3 2 8 0 3 7 3 3 3 4 3 1 3 3 3
--------删除所有给定值--------
2 8 0 7 4 1