package javaTest;
import java.util.*;
public class LinkList{
public Node head;
public Node current;
//方法:向链表中添加数据
public void add(int data){
//判断链表为空
if(head == null){ //若头结点为空,说明该链表未创建,把新的结点赋给头结点
head = new Node(data);
current = head;
}else{
//创建新的结点,放在当前结点的后面(把新的结点和链表进行关联)
current.next = new Node(data);
//把链表的当前索引向后移一位
current = current.next; //此步结束后,current结点指向新添加的结点
}
}
//方法重载:向链表中添加结点
public void add(Node node){
if(node == null){
return;
}
if (head == null){
head = node;
current = head;
}else{
current.next = node;
current = current.next;
}
}
//方法:遍历链表
public void print(Node node){
if (node == null){
return;
}
current = node;
while(current != null){
System.out.println(current.data);
current = current.next;
}
}
//方法:获取单链表的长度
public int getLength(Node head){
if(head == null){
return 0;
}
int length = 0;
Node current = head;
while(current != null){
length++;
current = current.next;
}
return length;
}
//方法:查找单链表中的倒数第k个结点(时间复杂度为O(n))
public Node findLastNode(Node head, int index){
//第一次遍历,得到链表的长度size
if(head == null){
return null;
}
int size = 0;
current = head;
while (current != null){
size++;
current = current.next;
}
//第二次遍历,输出倒数第index个结点的数据
current = head;
for(int i = 0; i < size - index; i++){
current = current.next;
}
return current;
}
public Node findLastNode2(Node head, int index){
if(index == 0 || head == null){ //注意index为0的情况
return null;
}
Node first = head;
Node second = head;
//让second结点往后挪k-1个位置
for(int i = 0; i < index; i++){
System.out.println("i的值是" + i);
second = second.next;
if (second == null){ //说明index的值大于链表的长度
//我们自己抛出异常,以提醒用户
// throw new NullPointerException("链表长度小于" + index);
return null;
}
}
//让first和second结点整体向后移动,直到second走到最后一个结点
while(second != null){
first = first.next;
second = second.next;
}
//当second走到最后一个结点时,first结点就是我们要找的倒数第index个结点
return first;
}
//方法:查找单链表中的中间节点
public Node findMidNode(Node head){
if (head == null){
return null;
}
Node first = head;
Node second = head;
while (second != null && second.next != null){
first = first.next;
second = second.next.next;
}
//直到second结点移动到null时,此时first指针指向的位置就是中间结点的位置
return first;
//当list的长度为偶数时,得到的中间结点是第(n/2+1)个
}
//方法:合并两个有序的单链表,合并之后的链表仍然有序
public Node mergeLinkedList(Node head1, Node head2){
if (head1 == null && head2 == null){
return null;
}
if (head1 == null){
return head2;
}
if (head2 == null){
return head1;
}
Node head; //新链表的头结点
Node current; //current结点指向新链表
//一开始,我们让current结点指向head1和head2中较小的数据,得到head结点
if (head1.data < head2.data){
head = head1;
current = head1;
head1 = head1.next;
}
else{
head = head2;
current =head2;
head2 = head2.next;
}
while(head1 != null && head2 != null){
if (head1.data < head2.data){
current.next = head1; //新链表中,current指针的下一个结点对应较小的那个数据
current = current.next; //current指针下移
head1 = head1.next;
}
else{
current.next = head2;
current = current.next;
head2 = head2.next;
}
}
if (head1 != null){ //说明链表2遍历完了,是空的
current.next = head1;
}
if (head2 != null){ //说明链表1遍历完了,是空的
current.next =head2;
}
return head;
}
//方法:单链表的反转
public Node reverseList(Node head){
//如果链表为空或者只有一个结点,无需反转,直接返回链表的头结点
if (head == null || head.next == null){
return head;
}
Node former = null;
Node current = head;
Node latter = null; //定义当前结点的的下一个结点
while(current != null){
latter = current.next; //保存当前结点的下一个结点
current.next = former; //当前结点的下一个结点变为former结点
former = current; //former结点更新为当前结点
current = latter; //current结点更新为之前保存的(原先的下一个结点)
}
return former;
}
//方法:从尾到头打印单链表
public void reversePrint(Node head){
//颠倒顺序,联想到栈,先进后出(时间复杂度O(n))
if (head == null){
return;
}
Stack<Node> stack = new Stack<Node>(); //新建一个栈
Node current = head;
while (current != null){
stack.push(current); //将当前结点压栈
current = current.next;
}
while (stack.size() > 0){
System.out.println(stack.pop().data); //出栈操作
}
}
public void reversePrint2(Node head){
//使用系统的栈,递归
if (head == null){
return;
}
reversePrint2(head.next);
System.out.println(head.data);
//当链表很长的时候,会导致方法的调用层级很深,可能会造成栈溢出
}
//方法:判断单链表是否有环
public boolean hasCycle(Node head){
if (head == null){
return false;
}
Node first = head;
Node second = head;
while (first != null && second != null && second.next != null){
first = first.next; //first指针走一步
second = second.next.next; //second指针走两步
if (first == second){
return true;
}
}
return false;
}
//方法:判断单链表是否有环;返回的结点是相遇的那个结点
public Node hasCycle2(Node head){
if (head == null){
return null;
}
Node first = head;
Node second = head;
while (first != null && second != null && second.next != null){
first = first.next; //first指针走一步
second = second.next.next; //second指针走两步
if (first == second){
return first; //将相遇的节点返回
}
}
return null;
}
//方法:有环链表中,获取环的长度,参数node代表的是相遇的那个结点
public int getCycleLength(Node node){
if (head == null){
return 0;
}
Node current = node;
// 该结点在环里,让该结点对应的指针一直往下走,直到回到原点
int length = 0;
// while (current.next != node){
// current = current.next;
// length++;
// }
// return (length+1);
while (current != null){
current = current.next;
length++;
if (current == node){
return length;
}
}
return length;
}
//方法:单链表中取出环的起始点
//方法:判断两个单链表相交的一个交点
public Node getFirstCommonNode(Node head1, Node head2){
if (head1 == null || head2 == null){
return null;
}
int length1 = getLength(head1);
int length2 = getLength(head2);
int lengthDif = 0; //两个链表长度的差值
Node longHead;
Node shortHead;
//找出较长的链表
if (length1 > length2){
longHead = head1;
shortHead = head2;
lengthDif = length1 - length2;
} else {
longHead = head2;
shortHead = head1;
lengthDif = length2 - length1;
}
//将较长的那个链表的指针向前走lengthDif个距离
for (int i = 0; i < lengthDif; i++){
longHead = longHead.next;
}
//将两个链表的指针同时向前移动
while (longHead != null && shortHead != null){
if (longHead == shortHead){ //第一个相同的结点就是相交的第一个结点
return longHead;
}
longHead = longHead.next;
shortHead = shortHead.next;
}
return null;
}
//结点内部类
class Node{ //内部类
int data; //数据域
Node next; //指针域
public Node(int data){
this.data = data;
}
}
public static void main(String[] args){
LinkList list = new LinkList();
//向链表中添加数据
for (int i = 0 ; i < 10; i++){
list.add(i);
}
list.print(list.head); //从head结点开始遍历输出
System.out.println("length of this list is " + list.getLength(list.head));
System.out.println(list.hasCycle(list.head));
System.out.println(list.findLastNode(list.head, 4).data);
System.out.println(list.findLastNode2(list.head, 4).data);
System.out.println(list.findMidNode(list.head).data);
LinkList list2 = new LinkList();
for(int j = 3; j < 8; j++){
list2.add(j);
}
LinkList list3 = new LinkList();
list3.head = list3.mergeLinkedList(list.head, list2.head);
list3.print(list3.head);
System.out.println("\n");
LinkList list4 = new LinkList();
list4.head = list3.reverseList(list3.head);
list4.print(list4.head);
System.out.println("\n");
list4.reversePrint(list4.head);
LinkList list5 = new LinkList();
for (int k = 0; k < 4; k++){
list5.add(k);
}
list5.add(list5.head); //将头结点添加到链表中,于是单链表就有环了
System.out.println(list5.hasCycle(list5.head));
Node thisNode = list5.hasCycle2(list5.head);
System.out.println(thisNode.data);
System.out.println(list5.getCycleLength(thisNode));
}
}
Java_链表(方法大全)
最新推荐文章于 2024-08-17 08:59:42 发布