JAVA中关于链表的操作和基本算法

本文总结了Java中单链表的基本操作,包括求链表长度、链表反转、查找倒数第K个节点等,并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.HashMap;
import java.util.Scanner;
import java.util.Stack;

/**
 *
 * @author kerryfish
 * 关于java中链表的操作
 * 1. 求单链表中结点的个数: getListLength
 * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
 * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
 * 4. 查找单链表的中间结点: getMiddleNode
 * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
 * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
 * 7. 对单链表进行排序,listSort(归并),insertionSortList(插入)
 * 8. 判断一个单链表中是否有环: hasCycle
 * 9. 判断两个单链表是否相交: isIntersect
 * 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap
 * 11. 给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete: deleteNode
 * 12. 以k个数为一组,反转链表。
 */
public class LinkedListSummary {
    /**
     * @param args
     *
     */
    public static class Node{
        int value;
        Node next;
        public Node(int n){
            this.value=n;
            this.next=null;
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in=new Scanner(System.in);
        Node head=null;
        if(in.hasNextInt()){
            head=new Node(in.nextInt());
        }
        Node temp=head;
        while(in.hasNextInt()){
            temp.next=new Node(in.nextInt());
            temp=temp.next;
        }
        in.close();
        //int len=getListLength(head);
        //Node reHead=reverseList(head);
        //reHead=reverseListRec(reHead);
        //Node node_k=reGetKthNode(head,3);
        //Node mid=getMiddleNode(head);
        //reversePrintListRec(head);
        //reversePrintListStack(head);
        //Node mergeHead=mergeSortedList(head,null);
        //Node sortHead=listSort(head);

    }
    //求单链表中结点的个数: getListLength
    public static int getListLength(Node head){
        int len=0;
        while(head!=null){
            len++;
            head=head.next;
        }
        return len;
    }
    //将单链表反转,循环
    public static Node reverseList(Node head){
        if(head==null||head.next==null)return head;
        Node pre=null;
        Node nex=null;
        while(head!=null){
            nex=head.next;
            head.next=pre;
            pre=head;
            head=nex;
        }
        return pre;
    }
    //将单链表反转,递归
    public static Node reverseListRec(Node head){
        if(head==null||head.next==null)return head;
        Node reHead=reverseListRec(head.next);
        head.next.next=head;
        head.next=null;
        return reHead;
    }
    //查找单链表中的倒数第K个结点(k > 0)
    public static Node reGetKthNode(Node head,int k){
        if(head==null)return head;
        int len=getListLength(head);
        if(k>len)return null;
        Node target=head;
        Node nexk=head;
        for(int i=0;i<k;i++){
            nexk=nexk.next;
        }
        while(nexk!=null){
            target=target.next;
            nexk=nexk.next;
        }
        return target;
    }
    //查找单链表的中间结点
    public static Node getMiddleNode(Node head){
        if(head==null||head.next==null)return head;
        Node target=head;
        Node temp=head;
        while(temp!=null&&temp.next!=null){
            target=target.next;
            temp=temp.next.next;
        }
        return target;
    }
    //从尾到头打印单链表,递归
    public static void reversePrintListRec(Node head){
        if(head==null)return;
        else{
            reversePrintListRec(head.next);
            System.out.println(head.value);
        }
    }
    //从尾到头打印单链表,栈
    public static void reversePrintListStack(Node head){
        Stack<Node> s=new Stack<Node>();
        while(head!=null){
            s.push(head);
            head=head.next;
        }
        while(!s.isEmpty()){
            System.out.println(s.pop().value);
        }
    }
    //合并两个有序的单链表head1和head2,循环
    public static Node mergeSortedList(Node head1,Node head2){
        if(head1==null)return head2;
        if(head2==null)return head1;
        Node target=null;
        if(head1.value>head2.value){
            target=head2;
            head2=head2.next;
        }
        else{
            target=head1;
            head1=head1.next;
        }
        target.next=null;
        Node mergeHead=target;
        while(head1!=null && head2!=null){
            if(head1.value>head2.value){
                target.next=head2;
                head2=head2.next;
            }
            else{
                target.next=head1;
                head1=head1.next;
            }
            target=target.next;
            target.next=null;
        }
        if(head1==null)target.next=head2;
        else target.next=head1;
        return mergeHead;
    }
    //合并两个有序的单链表head1和head2,递归
    public static Node mergeSortedListRec(Node head1,Node head2){
        if(head1==null)return head2;
        if(head2==null)return head1;
        if(head1.value>head2.value){
            head2.next=mergeSortedListRec(head2.next,head1);
            return head2;
        }
        else{
            head1.next=mergeSortedListRec(head1.next,head2);
            return head1;
        }
    }
    //对单链表进行排序,归并排序,在排序里面不建议选用递归的合并有序链表算法,如果链表长度较长,很容易出现栈溢出
    public static Node listSort(Node head){
        Node nex=null;
        if(head==null||head.next==null)return head;
        else if(head.next.next==null){
            nex=head.next;
            head.next=null;
        }
        else{
            Node mid=getMiddleNode(head);
            nex=mid.next;
            mid.next=null;
        }
        return mergeSortedList(listSort(head),listSort(nex));//合并两个有序链表,不建议递归
    }
    //对单链表进行排序,插入排序
    public Node insertionSortList(Node head) {
        if(head==null||head.next==null)return head;
        Node pnex=head.next;
        Node pnex_nex=null;
        head.next=null;
        while(pnex!=null){
            pnex_nex=pnex.next;
            Node temp=head;
            Node temp_pre=null;
            while(temp!=null){
                if(temp.value>pnex.value)break;
                temp_pre=temp;
                temp=temp.next;
            }
            if(temp_pre==null){
                head=pnex;
                pnex.next=temp;
            }
            else{
                temp_pre.next=pnex;
                pnex.next=temp;
            }
            pnex=pnex_nex;
        }
        return head;
    }
    //判断一个单链表中是否有环,快慢指针
    public static boolean hasCycle(Node head){
        boolean flag=false;
        Node p1=head;
        Node p2=head;
        while(p1!=null&&p2!=null){
            p1=p1.next;
            p2=p2.next.next;
            if(p2==p1){
                flag=true;
                break;
            }
        }
        return flag;
    }
    //判断两个单链表是否相交,如果相交返回第一个节点,否则返回null
    //如果单纯的判断是否相交,只需要看最后一个指针是否相等
    public static Node isIntersect(Node head1,Node head2){
        Node target=null;
        if(head1==null||head2==null)return target;
        int len1=getListLength(head1);
        int len2=getListLength(head2);
        if(len1>=len2){
            for(int i=0;i<len1-len2;i++){
                head1=head1.next;
            }
        }else{
            for(int i=0;i<len2-len1;i++){
                head2=head2.next;
            }
        }
        while(head1!=null&&head2!=null){
            if(head1==head2){
                target=head1;
                break;
            }
            else{
                head1=head1.next;
                head2=head2.next;
            }
        }
        return target;
    }
    //已知一个单链表中存在环,求进入环中的第一个节点,利用hashmap,不要用ArrayList,因为判断ArrayList是否包含某个元素的效率不高
    public static Node getFirstNodeInCycleHashMap(Node head){
        Node target=null;
        HashMap<Node,Boolean> map=new HashMap<Node,Boolean>();
        while(head!=null){
            if(map.containsKey(head))target=head;
            else{
                map.put(head, true);
            }
            head=head.next;
        }
        return target;
    }
    //已知一个单链表中存在环,求进入环中的第一个节点,不用hashmap
    //用快慢指针,与判断一个单链表中是否有环一样,找到快慢指针第一次相交的节点,此时这个节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
    public static Node getFirstNodeInCycle(Node head){
        Node fast=head;
        Node slow=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.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;

    }
    //给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete
    //可惜采用将delete节点value值与它下个节点的值互换的方法,但是如果delete是最后一个节点,则不行,但是总得复杂度还是O(1)
    public static void deleteNode(Node head,Node delete){
        //首先处理delete节点为最后一个节点的情况
        if(delete==null)return;
        if(delete.next==null){
            if(head==delete)head=null;
            else{
                Node temp=head;
                while(temp.next!=delete){
                    temp=temp.next;
                }
                temp.next=null;
            }
        }
        else{
            delete.value=delete.next.value;
            delete.next=delete.next.next;
        }
        return;
    }
    //以k个数为一组,反转链表
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode curr = head;
        int count = 0;
        while (curr != null && count != k) { // find the k+1 node
            curr = curr.next;
            count++;
        }
        if (count == k) { // if k+1 node is found
            curr = reverseKGroup(curr, k); // reverse list with k+1 node as head
            // head - head-pointer to direct part,
            // curr - head-pointer to reversed part;
            while (count-- > 0) { // reverse current k-group: 循环赋值,head.next -> temp -> head - >cur -> head.next
                ListNode tmp = head.next; // tmp - next head in direct part
                head.next = curr; // preappending "direct" head to the reversed list
                curr = head; // move head of reversed part to a new node
                head = tmp; // move "direct" head to the next node in direct part
            }
            head = curr;
        }
        return head;
    }
}


  链表类List的源代码如下: import Java.io.*; public class List {  /*用变量来实现表头*/  private Node Head=null;  private Node Tail=null;  private Node Pointer=null;  private int Length=0;  public void deleteAll()  /*清空整个链表*/  {   Head=null;   Tail=null;   Pointer=null;   Length=0;  }  public void reset()  /*链表复位,使第一个结点成为当前结点*/  {   Pointer=null;  }  public boolean isEmpty()  /*判断链表是否为空*/  {   return(Length==0);  }  public boolean isEnd()  /*判断当前结点是否为最后一个结点*/  {   if(Length==0)    throw new Java.lang.NullPointerException();   else if(Length==1)    return true;   else    return(cursor()==Tail);  }  public Object nextNode()  /*返回当前结点的下一个结点的值,并使其成为当前结点*/  {   if(Length==1)    throw new Java.util.NoSuchElementException();   else if(Length==0)    throw new Java.lang.NullPointerException();   else   {    Node temp=cursor();    Pointer=temp;    if(temp!=Tail)     return(temp.next.data);    else     throw new Java.util.NoSuchElementException();   }  }  public Object currentNode()  /*返回当前结点的值*/  {   Node temp=cursor();   return temp.data;  }     public void insert(Object d)  /*在当前结点前插入一个结点,并使其成为当前结点*/  {   Node e=new Node(d);   if(Length==0)   {    Tail=e;    Head=e;   }   else   {    Node temp=cursor();    e.next=temp;    if(Pointer==null)     Head=e;    else     Pointer.next=e;   }   Length++;  }  public int size()  /*返回链表的大小*/  {   return (Length);  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值