Java〖鏈表〗各種單鏈表的面試題,你真的做得出來嗎

實現功能

  • 鏈表無序加入數據
  • 打印所有節點信息
  • 有序插入節點
  • 修改節點數據
  • 刪除節點
  • 獲取鏈表有效節點個數
  • 獲取倒數第K個節點(思路:定義兩個指針變量一開始指向頭節點,讓第一個first先走k-1步,然後第二個second跟第一個一起走,當第一個走到頭後,輸出第二個就是倒數第K個元素)
  • 用棧來反轉鏈表
  • 使用頭插法反轉鏈表
  • 將兩個有序的鏈表合併(非遞歸)
  • 遞歸合併鏈表

可以看看註釋,面試的題與鏈表基本實現都有

package DataStructure.LinkListDemo;


import java.util.Stack;

//定義node
class Node{
    public int no;
    public String name;
    public Node next; //存放指向下一個節點的數據

    public Node(int no, String name) {
        this.no = no;
        this.name = name;
    }



    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

//實現鏈表功能
class LinkedListDemo{
    private Node head=new Node(-1,"");//初始化頭節點

    /**
     * 鏈表無序加入數據
     * @param node
     */
    public   void add(Node node){
        Node temp=head; //由於不能移動head,所以用temp代替
        while(true){
            if(temp.next==null){ //當找到下一個節點元素爲空是,就可以把新的數據加入到這裏
                break;
            }
            temp=temp.next; //當找不到時,一直向後找
        }
        temp.next=node;   //這裏加入新節點
    }

    /**
     * 打印所有節點信息
     */
    public void prtList(){
        if(head.next==null) System.out.println("鏈表爲空");
        Node temp=head.next; //由於不能移動head,所以用temp代替
        while(true){
            if(temp==null){ //判斷鏈表誰否到最後
                break;
            }
            System.out.println(temp);//輸出節點信息
            temp=temp.next;//節點後移
        }
    }

    /**
     *有序插入節點
     */
    public void addOrder(Node node){
        Node temp=head;
        boolean flag=false; //判斷是否重複添加
        while (true){  //查找該插入的節點位置
            if(temp.next==null){ //在鏈表最後
              break;
            }
            if(node.no<temp.next.no){  //這裏需要找到temp的下一個位置與插入的node比較,比temp的下一個元素小,那就可以插入到temp後面
                break; //位置已經找到
            }else if(temp.next.no==node.no){
                flag=true;
                break; //不能添加重複的元素
            }
            temp=temp.next; //向後移
        }
        if(flag) System.out.println("不能添加重複編號的節點: "+node);
        else {
            node.next=temp.next;
            temp.next=node;
        }
    }

    /**
     * 修改節點數據
     * @param node
     */
    public void updateNode(Node node){
        if(head.next==null) System.out.println("鏈表爲空,不能修改");
        Node temp=head.next;
        boolean flag=false;//表示是否找到修改的節點
        while (true){
            if(temp==null) break; //表示找到最後還是沒有找到
            if(temp.no==node.no){
                flag=true;//表示找到了
                break;
            }
            temp=temp.next;//接着向後查找
        }
        if(flag) {
            temp.name=node.name;
        }else{
            System.out.println("未發現存在的節點 :"+node);
        }
    }

    /**
     * 刪除節點
     * @param node
     */
    public void deleteNode(Node node){
        if(head.next==null) System.out.println("鏈表爲空,不能刪除");
        Node temp=head; //由於不能改變head的值,使用臨時變量
        boolean flag=false;//表示未能找到刪除節點
        while(true){
            if(temp.next==null){
                break; //表示未能找到當前刪除的節點
            }
            if(temp.next.no==node.no){  //表示找到要刪除的節點
                flag=true;
                break;
            }
            temp=temp.next;//找不到就向後找
        }
        if(flag){
            temp.next=temp.next.next;
        }else{
            System.out.println("未能找到刪除的節點: "+node);
        }
    }

    /**
     * 獲取鏈表有效節點個數
     * @return
     */
    public int getAllNodeNumber(){
        int num=0;
        if(head.next==null) return 0;
        Node temp=head.next;
        while (true){
            if(temp==null){
                break;
            }
            num++;
            temp=temp.next;
        }
        return num;
    }

    /**
     * 獲取倒數第K個節點(思路:定義兩個指針變量一開始指向頭節點,讓第一個first先走k-1步,然後第二個second跟第一個一起走,當第一個走到頭後,輸出第二個就是倒數第K個元素)
     */
    public void getLastK(int k){
        if(head.next==null) System.out.println("鏈表爲空");
        Node first=head;
        Node second=head;
        for (int i = 0; i < k-1; i++) {
            if(first.next==null) return;
            first=first.next;
        }
        while(first.next!=null){
            first=first.next;
            second=second.next;
        }
        System.out.println(second);
    }

    /**
     * 用棧來反轉鏈表
     */
    public void InverseList(){
        if(head.next==null) {
            System.out.println("鏈表爲空,不能反轉");
            return;
        }
        Node temp=head; //使用temp來遍歷list
        Node newTemp=head; //使用newTemp來串新鏈表
        Stack<Node> stack=new Stack<>(); //用棧來保存鏈表所有數據
        while(temp.next!=null){ //循環加入棧中
            stack.push(temp.next);
            temp=temp.next;
        }
        while(!stack.empty()){ // 當棧不爲空時,一直彈出,加到新節點後(改變原先順序)
            newTemp.next=stack.pop();
            newTemp=newTemp.next;
        }
//        while (stack.size()>0){ //不改變原先順序,直接打印出來
//            System.out.println(stack.pop());
//        }
        newTemp.next=null; //如果不設置最後一個節點的next域,那將會變成環形鏈表
    }

    /**
     * 使用頭插法反轉鏈表
     */
    public void reverse() {
        if (head.next == null || head.next.next == null)
            return ;
        Node cur=head.next;
        Node next=null;
        Node reserve=new Node(-1,"");
        while(cur!=null){
            next=cur.next;
            cur.next=reserve.next;
            reserve.next=cur;
            cur=next;
        }
        head.next=reserve.next;
    }

    /**
     * 將兩個有序的鏈表合併
     * @param list1
     * @param list2
     * @return
     */
    public Node mergeList(Node list1,Node list2){
        if(list1==null) return list2; //如果一條鏈表爲空,那就返回另一條鏈表
        if(list2==null) return list1;
        Node newNode=new Node(-1,""); //定義一個新鏈表頭
        Node temp=newNode; //頭不能變,所以定義臨時變量
        while((list1!=null)&&(list2!=null)){ //當只要有一個變量的值爲空就跳出循環
            if(list1.no>=list2.no){ //當list1.no>=list2.no
                temp.next=list2; //我們把小的連到頭的後面,下同
                list2=list2.next;
            }
            else {
                temp.next=list1;
                list1=list1.next;
            }
            temp=temp.next; //臨時變量向後移
        }
//        if(list1==null){
//            temp.next=list2;
//        }
//        else if (list2==null){
//            temp.next=list1;
//        }
        temp.next=list1==null?list2:list1; //當某一個鏈表的值爲空時,就將另一條鏈表連入新表
        return newNode.next; //返回新鏈表的第一個值
    }

    /**
     * 遞歸合併鏈表
     * @param list1
     * @param list2
     * @return
     */
    public Node mergeListDigui(Node list1,Node list2){
        if(list1==null) return list2;
        if(list2==null) return list1;
        if(list1.no<list2.no){
            list1.next= mergeListDigui(list1.next,list2);
            return list1;
        }else {
            list2.next = mergeListDigui(list1, list2.next);
            return list2;
        }
    }


}

//測試方法
public class LinkListDemo {

    public static void main(String[] args) {
        Node node=new Node(1,"kaikai");
        Node node1=new Node(2,"kaikai");
        Node node2=new Node(4,"kaikai");
        LinkedListDemo list=new LinkedListDemo();
//        list.addOrder(node);
//        list.addOrder(node1);
//        list.addOrder(node2);
//        list.prtList(); //打印鏈表

        Node node3=new Node(2,"kaikai1");
        Node node4=new Node(3,"kaikai");
        Node node5=new Node(8,"kaikai");

        node.next=node1;
        node1.next=node2;

        node3.next=node4;
        node4.next=node5;
		
		//合併鏈表
        Node node6 = list.mergeListDigui(node, node4);
        while(node6!=null){
            System.out.println(node6);
            node6=node6.next;
        }


//        final int allNodeNumber = list.getAllNodeNumber();
//        System.out.println("鏈表的有效個數爲: "+allNodeNumber);
//
//        System.out.println("鏈表反轉後爲: ");
//        list.reverse();
//        list.prtList();
//
//        System.out.println("得到鏈表倒數第K的節點爲: ");
//        list.getLastK(3);

        
//
//        System.out.println("修改數據後爲:");
//        Node node5=new Node(5,"kaikai55555");
//        list.updateNode(node5);
//        list.prtList();
//
//        System.out.println("刪除數據後爲:");
//        Node node6=new Node(5,"kaikai55555");
//        list.deleteNode(node6);
//        list.prtList();
    }
}

大佬們看着點噴 orz 給跪了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章