用java实现单链表的各种操作:
单链表的结构如下:
//定义一个单链表,内部类
private class Node {
private int data;
private Node next;
public Node() {}
public Node(int data) {
this.data = data;
}
}
具体代码如下:
package lianbiao;
//java中的LinkedList由双链表组成,这里使用单链表
public class MyLinkedList {
private Node head = null;
//定义一个单链表,内部类
private class Node {
private int data;
private Node next;
public Node() {}
public Node(int data) {
this.data = data;
}
}
1.增加到链表尾部
public void add(int data) {
Node node = new Node(data);
if(head == null) {
head = node;
return;
}
Node tmp = head;
while (tmp.next != null) {
tmp = tmp.next;
}
tmp.next = node;
}
2.删除第i个元素
public boolean delete(int index) {
if(index < 1 || index > length()) {
System.out.println("您输入的索引有误,不再范围内");
return false;
}
if(index == 1) {
head = head.next;
return true;
}
int i = 2;
Node cur = head;
while (cur != null) {
if(i == index) {
cur.next = cur.next.next;
break;
}
i++;
cur = cur.next;
}
return true;
}
3.计算该链表的长度
//计算该链表的长度
public int length() {
int count = 0;
Node cur = head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
4.对该链表进行排序
//对该链表进行排序
public void oderList() {
if(length() <= 1) {
return;
}
Node cur = head;
Node nextNode = null;
int temp = 0;
while (cur.next != null) {
nextNode = cur.next;
while (nextNode != null) {
if(cur.data > nextNode.data) {
temp = cur.data;
cur.data = nextNode.data;
nextNode.data = temp;
}
nextNode = nextNode.next;
}
cur = cur.next;
}
}
5.删除单链表中的重复元素
//删除单链表中的重复元素
public void deleteDuplecate() {
Node p = head;
while (p != null) {
Node q = p;
while (q.next != null) {
if (q.data == p.next.data) {
q.next = q.next.next;
}else {
q = q.next;
}
}
p = p.next;
}
}
6.打印该链表
//打印该链表
public void printList() {
Node cur = head;
while (cur != null) {
System.out.print(cur.data+",");
cur = cur.next;
}
System.out.println();
}
7.找出单链表的倒数第k个元素
//找出单链表的倒数第k个元素:
//思路:设置两个指针,让两个指针相差k-1个位置,当一个指针到达最后一个位置的时候,我们就能找到倒数第K个位置
public Node findElem(int k) {
if(k < 1) {
return null;
}
Node p1 = head;
Node p2 = head;
for(int i=0; i< k-1 && p1 != null; i++) {
p1 = p1.next;
}
if(p1 == null) {
System.out.println("k不合法");
return null;
}
while (p1.next != null) {
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
8.实现链表的反转,并返回反转链表以后的头结点
//实现链表的反转,并返回反转链表以后的头结点:
public void reverse() {
Node ReverseHead = head;
Node pNode = head;
Node pPrev = null;
//核心四步骤:
//Node pNext = pNode.next;
//pNode.next = pPrev;
//pPrev = pNode;
//pNode = pNext;
//循环指针为pNode,直到它为空
while (pNode != null) {
Node pNext = pNode.next;
//保证链表中所有的节点都进行了反转,并讲最后一个节点保存下来并赋值给ReverseHead
if(pNext == null) {
ReverseHead = pNode;
}
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
//最后将该链表的头结点进行反转
this.head = ReverseHead;
}
9.如何从尾到头输出链表中的元素
//如何从尾到头输出链表中的元素
public void printListReverse(Node head) {
if(head != null) {
printListReverse(head.next);
System.out.println(head.data);
}
}
10.寻找单链表的中间节点
//寻找单链表的中间节点:设置快慢节点,当快节点到达末尾是慢节点所指向的就是中间节点
public Node searchMid() {
Node fast = this.head;
Node slow = this.head;
while (fast != null && fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
11.如何检测一个链表是否有环
//如何检测一个链表是否有环
public boolean isLoop() {
Node fast = this.head;
Node slow = this.head;
if(fast == null) {
return false;
}
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
return true;
}
}
return false;
}
12.查找有环链表的环的入口
//查找有环链表的环的入口
public Node finLoopPort() {
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next;
if(slow == fast) {
break;
}
}
if(fast == null || fast.next == null) {
return null;
}
//慢指针从头结点开始,快指针从相遇的指针开始,当二者相遇的时候就是环的入口
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
13.如何在不知道头指针的情况下删除指定指针
//如何在不知道头指针的情况下删除指定指针
public boolean deleteNode(Node node) {
//这种方式无法删除链表的尾节点和空接点
if(node == null || node.next == null) {
return false;
}
int tmp = node.data;
node.data = node.next.data;
node.next = node.next.next;
return true;
}
14.判断两个链表是否相交:只考虑无环链表
//判断两个链表是否相交:只考虑无环链表
public boolean isIntersect(Node head1, Node head2) {
if(head1 == null || head2 == null) {
return false;
}
//找到链表head1的尾节点
Node tail1 = head1;
while (tail1.next != null) {
tail1 = tail1.next;
}
//找到head2的尾节点
Node tail2 = head2;
while (tail2.next != null) {
tail2 = tail2.next;
}
return tail1 == tail2;
}
15.如果两个链表相交,则如何找到相交的节点
//如果两个链表相交,则如何找到相交的节点
public Node getFirstMeetNode(Node head1, Node head2) {
if(head1 == null || head2 ==null) {
return null;
}
Node tail1 = head1;
int len1 = 1;
while (tail1.next != null) {
tail1 = tail1.next;
len1++;
}
Node tail2 = head2;
int len2 = 1;
while (tail2.next != null) {
tail2 = tail2.next;
len2++;
}
//如果两链表不相交,则直接返回null
if(tail1 != tail2) {
return null;
}
//设置两个指针,使其句交点相同的位置开始往后遍历,直到二者相遇,即就是交点的位置
Node t1 = head1;
Node t2 = head2;
//找出较长的链表
if(len1 > len2) {
int d = len1-len2;
while (d != 0) {
t1 = t1.next;
d--;
}
}else {
int d = len2-len1;
while (d != 0) {
t2 = t2.next;
d--;
}
}
while (t1 != t2) {
t1 = t1.next;
t2 = t2.next;
}
return t1;
}
以下对上述的方法进行测试代码
//以下对上述的方法进行测试
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.add(5);
list.add(1);
list.add(3);
list.add(6);
list.add(20);
list.add(9);
list.printList();
list.delete(3);
list.delete(3);
list.delete(3);
System.out.println("删除三个元素之后:");
list.printList();
list.oderList();
System.out.println("排序后:");
list.printList();
//验证findElemm(int k)的方法是否正确
list.add(10);
list.add(7);
list.add(6);
list.printList();
Node p3 = list.findElem(1);
Node p4 = list.findElem(3);
Node p5 = list.findElem(2);
System.out.println("倒数第一个数为:"+p3.data);
System.out.println("倒数第三个数为:"+p4.data);
System.out.println("倒数第二个数为:"+p5.data);
System.out.println("输出当前链表中的所有元素");
list.printList();
list.reverse();
System.out.println("输出链表进行翻转以后的元素");
list.printList();
System.out.println("从尾到头输出元素");
list.printListReverse(list.head);
}
}