数据结构——链表——双向循环链表

239 阅读1分钟

双向循环链表:

图解:

image.png

创建空链表:

class LinkList{
   constructor(){
  //头结点为空(头结点指向为空)
    this.head=null
   //尾结点为空(尾结点指向为空)
   this.tail=null
    //链表长度为0
    this.length=0
  }   
} 

创建节点元素:

class Dnode{
    // 封装一个构造函数,用于保存元素、元素的上一个引用及元素的下一个引用
    constructor(data){
        // 指向上一个元素节点
        this.prev=null
        // 存放数据
        this.data=data
        // 指向下一个节点(引用)
        this.next=null
    }
}

对链表进行操作(在链表中添加方法):

1.向链表最后添加元素 append(ele)

    append(ele) {
            let newnode = new Node(ele);

            if (this.length == 0) {
                //空链表
                this.head = newnode;
                this.tail = newnode;

                newnode.prev = this.tail;
                newnode.next = this.head;
            } else {

                // 将新节点连接
                newnode.prev = this.tail;
                newnode.next = this.head;

                // 断开原来的指向,重新指向新节点
                this.tail.next = newnode;
                this.head.prev = newnode;

                this.tail = newnode;
            }

            this.length++
        }

图解:

1.this.length=0

image.png

2.this.length!=0

image.png

2.向链表中的特定位置插入一个新的节点 insert(position,ele)

      insert(position, ele) {
            if (position < 0 || position > this.length || !Number.isInteger(position)) return
            let newnode = new Node(ele);

            if (position == 0) {
                if (this.length == 0) {
                    //空链表
                    this.head = newnode;
                    this.tail = newnode;
                    newnode.prev = this.tail;
                    newnode.next = this.head;
                } else {
                    newnode.prev = this.tail;
                    newnode.next = this.head;
                    this.head.prev = newnode
                    this.tail.next = newnode;
                    this.head = newnode;
                }
                this.length++
            }else if(position == this.length){
                this.append(ele)
            }else{
                let current = this.head,index = 0;
                while(index< position-1){
                    current = current.next;
                    index++;
                }
                newnode.prev = current;
                newnode.next = current.next;
                current.next = newnode;
                newnode.next.prev = newnode;
                this.length++
            }
        }

image.png

image.png

3.从链表的特定位置移除一项 removeAt(position)

     removeAt(position){
            if (position < 0 || position > this.length-1 || !Number.isInteger(position)) return

            if(position == 0){
                if(this.length == 1){
                    this.head = null;
                    this.tail = null;
                }else{
                    this.head = this.head.next;
                    this.tail.next = this.head;
                    this.head.prev = this.tail;
                }
                
            }else if(position == this.length-1){
                this.tail = this.tail.prev;
                this.tail.next = this.head;
                this.head.prev = this.tail;
            }else{
                let current = this.head,index= 0;
                while(index < position-1){
                    current = current.next;
                    index++;
                }
                current.next = current.next.next;
                current.next.prev = current
            }
            this.length--
        }

4.返回元素在链表中的索引,如果链表中没有该元素则返回-1. indexOf(ele)

   indexOf(ele){
            let current = this.head,index=0;
            while(index < this.length){
                if(current.data == ele){
                    return index
                }else{
                    current = current.next;
                    index++
                }
            }

            return -1
        }

5.从链表中移除指定元素 remove(ele)

      remove(ele){
            this.removeAt(this.indexOf(ele))
        }

6.如果链表中不包含任何元素,返回true,如果链表长度大于0,则返回false。 isEmpty()

isEmpty(){
            if(this.length==0){
                return true
            }else{
                return false
            }
        }

7.返回链表包含的元素个数。与数组的length属性类似。 size()

     size(){
        return this.length
       }

8.由于链表项使用了node类,就需要重写继承自javaScript对象默认的toString方法,让其只输出元素的值 toString()

1.正向遍历:

   toAfterString(){
            let current= this.head,index=0,res ="";

            while(index < this.length){
                res+= "-" + current.data;
                current = current.next;
                index++;
            }

            return res.slice(1)
        }

2.反向遍历:

           toBeforeString(){
            let current= this.tail,index=this.length-1,res ="";

            while(index >= 0){
                res+= "-" + current.data;
                current = current.prev;
                index--;
            }

            return res.slice(1)
        }

完整的代码:

      <script>
    class Node {
        constructor(data) {
            this.prev = null;
            this.data = data;
            this.next = null;
        }
    }
    class CycleDoubleLinkList {
        constructor() {
            this.head = null;
            this.tail = null;
            this.length = 0;
        }

        // 1.向链表最后添加元素
        append(ele) {
            let newnode = new Node(ele);

            if (this.length == 0) {
                //空链表
                this.head = newnode;
                this.tail = newnode;

                newnode.prev = this.tail;
                newnode.next = this.head;
            } else {

                // 将新节点连接
                newnode.prev = this.tail;
                newnode.next = this.head;

                // 断开原来的指向,重新指向新节点
                this.tail.next = newnode;
                this.head.prev = newnode;

                this.tail = newnode;
            }

            this.length++
        }

        // 2.向链表中的指定位置插入元素
        insert(position, ele) {
            if (position < 0 || position > this.length || !Number.isInteger(position)) return
            let newnode = new Node(ele);

            if (position == 0) {
                if (this.length == 0) {
                    //空链表
                    this.head = newnode;
                    this.tail = newnode;
                    newnode.prev = this.tail;
                    newnode.next = this.head;
                } else {
                    newnode.prev = this.tail;
                    newnode.next = this.head;
                    this.head.prev = newnode
                    this.tail.next = newnode;
                    this.head = newnode;
                }
                this.length++
            }else if(position == this.length){
                this.append(ele)
            }else{
                let current = this.head,index = 0;
                while(index< position-1){
                    current = current.next;
                    index++;
                }
                newnode.prev = current;
                newnode.next = current.next;
                current.next = newnode;
                newnode.next.prev = newnode;
                this.length++
            }
        }
   

        // 3.移除指定位置的元素
        removeAt(position){
            if (position < 0 || position > this.length-1 || !Number.isInteger(position)) return

            if(position == 0){
                if(this.length == 1){
                    this.head = null;
                    this.tail = null;
                }else{
                    this.head = this.head.next;
                    this.tail.next = this.head;
                    this.head.prev = this.tail;
                }
                
            }else if(position == this.length-1){
                this.tail = this.tail.prev;
                this.tail.next = this.head;
                this.head.prev = this.tail;
            }else{
                let current = this.head,index= 0;
                while(index < position-1){
                    current = current.next;
                    index++;
                }
                current.next = current.next.next;
                current.next.prev = current
            }
            this.length--
        }
   

        // 4.查找
        // 4.查找指定元素
        indexOf(ele){
            let current = this.head,index=0;
            while(index < this.length){
                if(current.data == ele){
                    return index
                }else{
                    current = current.next;
                    index++
                }
            }

            return -1
        }

         // 5.移除指定元素
         remove(ele){
            this.removeAt(this.indexOf(ele))
        }


        toAfterString(){
            let current= this.head,index=0,res ="";

            while(index < this.length){
                res+= "-" + current.data;
                current = current.next;
                index++;
            }

            return res.slice(1)
        }

        toBeforeString(){
            let current= this.tail,index=this.length-1,res ="";

            while(index >= 0){
                res+= "-" + current.data;
                current = current.prev;
                index--;
            }

            return res.slice(1)
        }
    }
    // 测试代码:

    let list = new CycleDoubleLinkList();
   

    for (let i = 0; i < 9; i++) {
        list.append(i)
    }

    list.remove("hello")
    list.remove(0)
    list.remove(6)
    list.remove(8)


    console.log(list.toAfterString());
    console.log(list.toBeforeString());
</script>