JAVA單鏈表的簡單操作(遞增單鏈表插入數據,鏈表逆置,鏈表逆序合成)

JAVA寫一個單鏈表

1、已知帶頭結點的動態單鏈表 L 中的結點是按整數值遞增排序的,試寫一 算法將值爲 x 的結點插入到表 L 中,使 L 仍然有序。要求算法的時間複雜度爲 O(n),空間複雜度爲 O(1)。

2、設計一算法,逆置帶頭結點的動態鏈表 L。要求利用原表的結點空間, 並要求用盡可能少的時間完成。

3、假設有兩個按元素值遞增有序的線性表 A 和 B,均以單鏈表作存儲結構, 試編寫算法將 A 表和 B 表歸併成一個按元素值遞減有序的線性表性表 C,並要求 利用原表的空間存放 C,並要求用盡可能少的時間完成。

如何插入一段漂亮的代碼片

  • 要求一:不破壞表的順序插入元素,時間複雜度O(n)
    一個for循環即可解決
//     
public void Insert_order(int e){
        Node current = header;
        if(header == null) //空表直接尾部加
            add(e);//在尾部添加元素
        int i;
        for(i=0;i<size&&current!=null;i++,current=current.next){
            if(current.data>=e){//如果某個結點的指大於等於輸入值
                if(i==0) {//如果是在頭節點,直接加在前面
                    addHead_e(e);//在頭部添加元素
                    break;
                }
                Node p=this.getNodeByIndex(i-1);//指定位置的前一個節點
                p.next=new Node(e,p.next);//這是不在首位的情況,獲取當前節點的前一個節點並將e插在它後面,同時新節點的指向是原節點的下一個節點
                size++;
                break;
            }
        }
        if(i==size)//如果循環沒有被break結束,那麼i的值與size的值相等,
            add(e);//這說明這個元素比原鏈表中任何一個都大,直接在尾部添加節點即可
        //System.out.println(size);

    }

用到的add(e)和addHead_e(e)方法:

//直接在尾部插入元素
    public void add(int e){
        if(header==null) {
            header = new Node(e, null);
            tail = header;
        }
        else{
            Node p=new Node(e,null);
            tail.next=p;
            tail=p;
        }
        size++;
    }
    //在表頭插入元素
    public void addHead_e(int e){
        Node p=new Node(e,null);
        p.next=header;
        header=p;
        if(header.next==null)
            tail=header;
        size ++;
    }

用到的getNodeByIndex(index)方法:

    // 獲取指定節點
   private Node getNodeByIndex(int index){
       if(index < 0 || index >= size)
           throw new IndexOutOfBoundsException("索引超出線性表範圍");
       Node current = header;//從header開始遍歷

       for(int i=0; i<size && current!=null; i++,current=current.next){
               if(i == index)
                   return current;
       }
       return null;
   }
  • 要求2:逆置帶頭結點的動態單鏈表 L
    一共有三種方法,這裏選擇的是迭代法
    事實上這裏可以不需要返回值的,截至到header=p就可以了
    具體結合實際應用
//逆置(迭代法)
   /*
   1.先將當前節點的下一節點記錄下來,
   2.然後將當前節點指向上一節點
   3.再將當前節點記錄下來,讓記錄的下一節點變成當前節點
   * */
   public Node ReverseLink1(){
       if(header==null||header.next==null)//如果表頭爲空或者當前鏈表只有一個節點,
           return header;                 //那麼直接返回就可以了
       Node p,q;
       p=null;//p用來保存上一節點,開始時,表頭沒有上一節點(表頭的上一節點爲空)
       q=header;//q用來保存當前節點,從表頭開始操作
       while(q!=null){//只要當前節點不爲空,就要進行操作
           Node r=q.next;////1.r保存當前節點的下一節點
           q.next=p;//2.讓當前節點指向上一節點,第一次爲空,第二次開始指向上一節點
           p=q;//3.讓上一節點變成當前節點(把當前節點記錄下來,記錄進p裏)
           q=r;//3.讓記錄的下一節點變成當前節點
       }
       header=p;
       return header;
   }
  • 要求三:元素值遞增有序的線性表 A 和 B,以單鏈表作存儲結構,將 A 表和 B 表歸併成一個按元素值遞減有序的線性表性表 C,並要求 利用原表的空間存放 C
    -------------------------------------------------------------------------------------也就是
    將A和B兩個遞增單鏈表合成遞減單鏈表並要求用原來的存儲空間
    這裏我的想法是這樣的:把B表的元素一個一個拿出來,插入到A表中再逆置
  /*
兩個遞增鏈表合成一個遞減鏈表
利用前面的函數和輔助節點p,將b鏈表的值按大小順序插入到a表中,
形成包含a和b所有元素的遞增鏈表,再將鏈表用寫好的逆置方法逆置就可以了
* */
   public void Combine_order_increase(My_list b) {
       Node p,q;
       p=this.header;
       q=b.header;
       while(p!=null&&q!=null)
       {
          this.Insert_order(q.data);
//           System.out.println("t "+this+" t");
//            System.out.println("m "+b+" m");
          q=q.next;
       }
       this.ReverseLink1();
   }
  • 完整代碼如下:

      private class Node{
          private int data;
          private Node next;
          public Node() {}
          // 初始化全部屬性的構造器
          public Node(int data, Node next) {
              this.data = data;
              this.next = next;
          }
      }
      public Node header;// 保存頭結點
      private Node tail;// 保存尾節點
      private int size;// 保存已含有的節點數
      public void Input_size(int size){
          this.size=size;
      }
      public My_list(){
          header=null;
          tail=null;
      }
      public My_list(int e){
          header=new Node(e,null);
          tail=header;
          size++;
      }
      public int length(){
          return  size;
      }
      // 獲取指定節點
    
    private Node getNodeByIndex(int index){
         if(index < 0 || index >= size)
             throw new IndexOutOfBoundsException("索引超出線性表範圍");
         Node current = header;//從header開始遍歷
    
         for(int i=0; i<size && current!=null; i++,current=current.next){
                 if(i == index)
                     return current;
         }
         return null;
     }
     // 獲取指定索引處的元素
     public int get(int index) {
         return this.getNodeByIndex(index).data;
     }
     public int locate(int e){
         Node current=header;
         for(int i=0;i<size&&current!=null;i++,current=current.next){
             if(current.data==e)
                 return i;
         }
         throw new IndexOutOfBoundsException("索引超出線性表範圍");
     }
     //指定位置插入元素
     public void Insert(int e,int index){
         if(index<0||index>=size)
             throw new IndexOutOfBoundsException("索引超出線性表範圍");
        // Node current =header;
         if(header == null)//空表直接尾部加
             add(e);
         else{
             if(index==0)//表頭直接在頭部加(已排除空表)
                 addHead_e(e);
             else{
                 Node p=getNodeByIndex(index-1);//指定位置的前一個節點
                 p.next=new Node(e,p.next);
             }
         }
         size++;
     }
    
    ```//直接在尾部插入元素
     public void add(int e){
         if(header==null) {
             header = new Node(e, null);
             tail = header;
         }
         else{
             Node p=new Node(e,null);
             tail.next=p;
             tail=p;
         }
         size++;
     }
     //在表頭插入元素
     public void addHead_e(int e){
         Node p=new Node(e,null);
         p.next=header;
         header=p;
         if(header.next==null)
             tail=header;
         size ++;
     }
     public void Insert_order(int e){
         Node current = header;
    
         if(header == null) {//空表直接尾部加
    
             add(e);
         }
         int i;
         for(i=0;i<size&&current!=null;i++,current=current.next){
    
             if(current.data>=e){//如果某個結點的指大於等於輸入值
                 if(i==0) {//如果是在頭節點,直接加在前面
                     addHead_e(e);
                     break;
                 }
                 Node p=this.getNodeByIndex(i-1);//指定位置的前一個節點
                 p.next=new Node(e,p.next);//這是不在首位的情況,獲取當前節點的前一個節點並將e插在它後面,同時新節點的指向是原節點的下一個節點
                 size++;
                 break;
             }
         }
         if(i==size)//如果循環沒有被break結束,那麼i的值與size的值相等,
             add(e);//這說明這個元素比原鏈表中任何一個都大,直接在尾部添加節點即可
         //System.out.println(size);
    
     }
    
      /*
      1.先將當前節點的下一節點記錄下來,
      2.然後將當前節點指向上一節點
      3.再將當前節點記錄下來,讓記錄的下一節點變成當前節點
      * */
      public Node ReverseLink1(){
          if(header==null||header.next==null)//如果表頭爲空或者當前鏈表只有一個節點,那麼直接返回就可以了
              return header;
          Node p,q;
          p=null;//p用來保存上一節點,開始時,表頭沒有上一節點(表頭的上一節點爲空)
          q=header;//q用來保存當前節點,從表頭開始操作
          while(q!=null){//只要當前節點不爲空,就要進行操作
              Node r=q.next;////1.r保存當前節點的下一節點
              q.next=p;//2.讓當前節點指向上一節點,第一次爲空,第二次開始指向上一節點
              p=q;//3.讓上一節點變成當前節點(把當前節點記錄下來,記錄進p裏)
              q=r;//3.讓記錄的下一節點變成當前節點
          }
          header=p;
          return header;
      }
    
    ```///*
    兩個遞增鏈表合成一個遞減鏈表
    利用前面的函數和輔助節點p,將b鏈表的值按大小順序插入到a表中,
    形成包含a和b所有元素的遞增鏈表,再將鏈表用寫好的逆置方法逆置就可以了
    //* */
     public void Combine_order_increase(My_list b) {
          Node p,q;
          p=this.header;
          q=b.header;
          while(p!=null&&q!=null)
          {
              this.Insert_order(q.data);
    //           System.out.println("t "+this+" t");
    //            System.out.println("m "+b+" m");
              q=q.next;
          }
          this.ReverseLink1();
      }
      @Override//重寫
      public String toString() {//作輸出用
          if(header==null){
              return null;
          }
          else{
              StringBuffer sb=new StringBuffer("");
              for(Node current = header; current != null; current = current.next)
                  sb.append(current.data).append(" ");
              int len = sb.length();
              return sb.toString();
          }
      }
    }
    
    

主程序入口:


public class Test {
   public static void main(String[] args) throws IOException {
       My_list a = new My_list();
       My_list b = new My_list();
       int t=1;
       int size_a;
       int size_b;
       while (t!=0){
           System.out.println("Please choose the function");
           System.out.println("1.initialize the “a” linklist and the “b” linklist");
           System.out.println("2.insert one data into “a” list");
           System.out.println("3.reverse the a list ");
           System.out.println("4.Combine the a and b list");
           System.out.println("5.Output the a and b list");
           t=KeyInput.readInt();
           switch (t){
               case 1:
                   System.out.println("Please input the size of a list");
                   size_a=KeyInput.readInt();
                  // a.Input_size(size_a);
                   System.out.println("Please input the size of b list");
                   size_b=KeyInput.readInt();
                  // b.Input_size(size_b);
                   System.out.println("Please input the data of a list");
                   for(int i=0;i<size_a;i++) {
                       int e=KeyInput.readInt();
                       a.add(e);
                   }
                   System.out.println("Please input the data of b list");
                   for(int i=0;i<size_b;i++) {
                       int e = KeyInput.readInt();
                       b.add(e);
                   }

                   break;
               case 2:
                   int e=KeyInput.readInt();
                   a.Insert_order(e);
                   break;
               case 3:a.ReverseLink1();
                   break;
               case 4:a.Combine_order_increase(b);
                   break;
               case 5:
                   System.out.println(a);
                   System.out.println(b);
                   break;
               case 0:
                   System.out.println("Welcome to Use Again!");
                   break;
               default:
                   System.out.println("No such a funcation was found");
                   System.out.println("Press any Key to Continue  ");
                   System.in.read( );
                   break;
           }
       }
   }
}


代碼參考了其他人的想法,事實上是一個修改和添加功能使其適應題目,參考的鏈接:
鏈接:自己動手寫一個單鏈表.
鏈接:鏈表的逆置(迭代法與逆置法).

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