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;
           }
       }
   }
}


代码参考了其他人的想法,事实上是一个修改和添加功能使其适应题目,参考的链接:
链接:自己动手写一个单链表.
链接:链表的逆置(迭代法与逆置法).

发布了1 篇原创文章 · 获赞 2 · 访问量 46

猜你喜欢

转载自blog.csdn.net/qq_44095715/article/details/105046430