数据结构——合并两条有序链表为一条有序链表

175 阅读2分钟

练习:

合并两条有序链表为一条有序链表:

list1:1 4 6 7

list2: 2 5 8 9

newlist:1 2 4 5 6 7 8 9

代码:

 <!-- 合并两条有序链表 -->
 
<script>
    const link1 = new LinkedList()
    link1.append(1)
    link1.append(3)
    link1.append(4)
    link1.append(6)
    link1.append(7)


    const link2 = new LinkedList()
    link2.append(2)
    link2.append(5)
    link2.append(8)
    link2.append(9)



    function mergerlist(list, otherlist) {

        // 1.创建新链表
        let newlist = new LinkedList();

        let listHead = list.head;
        let otherlistHead = otherlist.head;

        // 2.比较
        // 只要两个链表都还有元素,就继续比较
        while (listHead && otherlistHead) {
            if (listHead.data < otherlistHead.data) {
                // 当第一条链表list指向的data值小于第二条链表otherlist指向的data值
                // 在新链表中添加list指向的data值
                newlist.append(listHead.data);
                listHead = listHead.next;
            } else {
                // 当第二条链表otherlist指向的data值小于第一条链表list指向的data值
                // 在新链表中添加otherlist指向的data值
                newlist.append(otherlistHead.data);
                otherlistHead = otherlistHead.next;
            }
        }

        // 3.list为空,另一个链表otherlist中的数据依次添加到新链表中
        while(otherlistHead){
            newlist.append(otherlistHead.data);
            otherlistHead = otherlistHead.next
        }

         // 3.otherlist为空,另一个链表list中的数据依次添加到新链表中
        while(listHead){
            newlist.append(listHead.data);
            listHead = listHead.next
        }

        return newlist.toString();
        

    }

    console.log(mergerlist(link1, link2));

   
</script>

图解:

image.png

LinkedList代码:

 <script>
    // 封装一个构造函数,用于保存元素和元素的下一个引用
    class Londe{
        constructor(data){
            // 存放数据
            this.data=data;
            // 指向下一个节点(引用)
            this.next=null;
        }
    }
    class LinkList{
        constructor(){
            this.head=null
            this.length=0
        }   
        // 1.append()  向链表最后添加元素
        append(ele){
            // 创建新节点
            let newnode=new Londe(ele);
            // 判断头结点是否为空
            if(this.head==null){
                //头结点指向新节点 
                this.head=newnode
            }else{
                // 声明一个current指向头结点的指向
                let current=this.head
                while(current.next!=null){
                    // 当current的指向一直不为空时,
                    // 就随着当时指向的元素节点继续指向它的下一个元素节点
                    // 直到current的指向为空,就不再执行
                    current=current.next
                }  
                
                // 当current 表示最后一个节点时
                //令current的指向指向新节点
                // 这就是向链表尾部添加新节点
                current.next=newnode   
               }
            //    添加了元素,length长度就+1
               this.length++
        }  
        // 2.insert(指定位置,插入的元素)
        insert(position,ele){
            // 位置是否合法
            // Number.isInteger():用来判断给定的参数是否为整数
            if(position<0||position>this.length||!Number.isInteger(position)){
                return false
            }
            // 创建一个新节点
            let  newnode=new Londe(ele)
            // 2.1在头部位置插入
            if(position==0){
                if(this.head==null){
                    // 如果头部指向空,那么就让头部指向新的节点
                    this.head=newnode
                }else{
                    // 如果头部不为空,
                    // 那么就先让新节点指向头部指向的节点
                    // 再让头部指向新节点
                    newnode.next=this.head
                    this.head=newnode 
                }
                // 插入了一个新节点,链表中的节点数就+1
                this.length++
            }else if(position==this.length){
                // 2.2在尾部位置插入
                // 就直接使用上面的向链表最后添加元素的方法,就行
                this.append(ele)

            }else{
                // 2.3在任意位置插入
                // 创建一个变量,让它指向链表中头部指向的节点
                let current=this.head;
                // 创建一个变量index,方便知道节点的位置,以及current的具体指向节点位置
                let index=0
                // 前一个节点   position-1位置的节点
                while(index<position-1){
                    // 已知你想要插入节点的准确位置
                    // 从链表的第一个位置开始比较
                    // 通过index改变移动current指向的节点
                    // 直到index=position-1时,结束
                    current=current.next;
                    index++
                }
                // current就是插入节点位置的前一个节点
                newnode.next=current.next
                current.next=newnode
                this.length++
            }
        }
        // 3.removeAt(position)  移除指定位置的元素
        removeAt(position){
            // 位置是否合法
            if(position<0||position>=this.length-1||!Number.isInteger(position)){
                return false
            }
            if(this.head==null){
                // 空链表
                return 
            }else{
                // 非空链表
                if(position==0){
                    // 移除头部元素
                    this.head=this.head.next
                }else{
                    // 移除其他位置的元素
                    let current=this.head,index=0;
                    while(index<position-1){
                        // 已知你想要移除节点的准确位置
                    // 从链表的第一个位置开始比较
                    // 通过index改变移动current指向的节点
                    // 直到index=position-1时,结束
                        current=current.next;
                        index++
                    }
                    // 将移除节点的前面一个节点指向移除节点的后面一个节点
                    current.next=current.next.next
                }
                // 移除节点,链表中节点数-1
                this.length--
            }
        }
        // 4.indexOf(ele)  查找指定元素的位置,存在返回index,不存在返回-1
        indexOf(ele){
            let current=this.head,index=0
            while(index<this.length){
                // 遍历链表中的所有节点
                if(current.data==ele){
                    // 如果current指向的节点中的数据与我们查找的指定元素一致
                    // 就返回当前current指向的节点的位置
                    return index
                }else{
                    // 如果current指向的节点中的数据与我们查找的指定元素不一致
                    // 继续找
                    // 并且,index位置向后移动,,也就是+1
                    // current的指向,随着index的位置改变
                    current=current.next
                    index++
                }
            }
            // 找完了所有,都没有找到,返回-1
            // 表明链表中没有相对应的节点
            return -1
        }
        // 5.remove(ele)  移除指定元素
        remove(ele){
            // 查询指定元素所在的节点位置
            let index=this.indexOf(ele)
            // 移除该位置的指定元素
            this.removeAt(index)
        }
        // 6.将链表中的数据连接为字符串
        toString(){
            let current=this.head,index=0,res="";
            while(index<this.length){
                // 将current指向的节点的数据连接为字符串
                res+="-"+current.data;
                current=current.next ;
                index++
           }
        //    利用字符串的slice(start,end)方法, 提取字符串的片断,并在新的字符串中返回被提取的部分。
           return res.slice(1)
        }
        // 7.isEmpty():如果链表中不包含任何元素,返回true,如果链表长度大于0,则返回false。
        isEmpty(){
            if(this.length==0){
                return true
            }else{
                return false
            }
        }
        // 8.size():返回链表包含的元素个数。与数组的length属性类似。  
       size(){
        return this.length
       }
    }
  </srcipt>