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

136 阅读2分钟

单向循环链表:

图解:

image.png

创建空链表:

class LinkList{
        constructor(){
            this.head=null
            this.length=0
        }

创建节点元素:

class Cnode{
        constructor(data){
            this.data=data
            this.next=null
        }
    } 

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

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

    append(ele){
            let newnode=new Cnode(ele)
            if(this.head==null){
                // 空链表
                this.head=newnode
                newnode.next=this.head
            }else{
                // 非空链表
                // 需要找到最后一个节点
                // 最后一个节点.next指向头结点
                let current=this.head
                while(current.next!=this.head){
                    // 继续向后查找
                    current=current.next
                }
                // 找到了,current表示最后一个节点
                current.next=newnode
                newnode.next=this.head
            }
        } 

图解:

1.this.length=0

image.png

2.this.length!=0

image.png

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

      insert(position,ele){
         // 位置是否合法
            // Number.isInteger():用来判断给定的参数是否为整数
            if(position<0||position>this.length||!Number.isInteger(position)){
                return false
            }
            // 创建一个新节点
            let  newnode=new Conde(ele)
            let current=this.head
            let index=0
            // 2.1在头部位置插入
            if(position==0){
                if(this.length==0){
                    // 如果头部指向空,那么就让头部指向新的节点
                    this.head=newnode
                    newnode.next=this.head
                }else{
                while(current.next!=this.head){
                    current=current.next;
                }
                newnode.next=this.head
                current.next=newnode
                this.head=newnode
            }
            
        }else if(position==this.length){
            this.append(ele)
        }else{
            while(index<position-1){
                current=current.next
                index++
            }
            newnode.next=current.next
            current.next=newnode

        }
        this.length++
    }

image.png

image.png

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

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

            let current = this.head,
                index = 0;

            if (position == 0) {
                if (this.len == 1) {
                    this.head = null;
                } else {
                    while (current.next != this.head) {
                        current = current.next;
                    }

                    this.head = this.head.next;
                    current.next = this.head;
                }

            } else {
                while (index < position - 1) {
                    current = current.next;
                    index++;
                }

                current.next = current.next.next
            }
            this.length--
        }

图解:

1.position=0

image.png

2.position=this.length-1

image.png

3.0<position&&position<this.length-1

image.png

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

   indexOf(ele) {
            let current = this.head,index=0;
            while(index < this.len){
                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()

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

完整的代码:

      <script>
    class Cnode {
        constructor(data) {
            this.data = data
            this.next = null
        }
    }
    class LinkList {
        constructor() {
            this.head = null
            this.length = 0
        }
        // 1.append()  向链表最后添加元素
        append(ele) {
            let newnode = new Cnode(ele)
            if (this.head == null) {
                // 空链表
                this.head = newnode
                newnode.next = this.head
            } else {
                // 非空链表
                // 需要找到最后一个节点
                // 最后一个节点.next指向头结点
                let current = this.head
                while (current.next != this.head) {
                    // 继续向后查找
                    current = current.next
                }
                // 找到了,current表示最后一个节点
                current.next = newnode
                newnode.next = this.head
            }
            this.length++
        }
        // 2.insert(指定位置,插入的元素)
        insert(position, ele) {
            // 位置是否合法
            // Number.isInteger():用来判断给定的参数是否为整数
            if (position < 0 || position > this.length || !Number.isInteger(position)) {
                return false
            }
            // 创建一个新节点
            let newnode = new Conde(ele)
            let current = this.head
            let index = 0
            // 2.1在头部位置插入
            if (position == 0) {
                if (this.length == 0) {
                    // 如果头部指向空,那么就让头部指向新的节点
                    this.head = newnode
                    newnode.next = this.head
                } else {
                    while (current.next != this.head) {
                        current = current.next;
                    }
                    newnode.next = this.head
                    current.next = newnode
                    this.head = newnode
                }

            } else if (position == this.length) {
                this.append(ele)
            } else {
                while (index < position - 1) {
                    current = current.next
                    index++
                }
                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
            }

            let current = this.head,
                index = 0;

            if (position == 0) {
                if (this.len == 1) {
                    this.head = null;
                } else {
                    while (current.next != this.head) {
                        current = current.next;
                    }

                    this.head = this.head.next;
                    current.next = this.head;
                }

            } else {
                while (index < position - 1) {
                    current = current.next;
                    index++;
                }

                current.next = current.next.next
            }
            this.length--
        }
        // 4.indexOf(ele)  查找指定元素的位置,存在返回index,不存在返回-1
        indexOf(ele) {
            let current = this.head,index=0;
            while(index < this.len){
                if(current.data == ele){
                    return index
                }else{
                    current = current.next;
                    index++
                }
            }

            return -1

        }
        // 5.remove(ele)  移除指定元素
        remove(ele){
            this.removeAt(this.indexOf(ele))
        }
        // 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
       }
    }
    // 测试代码:
    let list = new LinkList();
    list.append(4)
    for (let i = 0; i < 4; i++) {
        list.append(i)
    }
    list.removeAt(2)
    console.log(list)
    console.log(list.toString())

</script>