js实现数据结构—链表

一、单链表构造函数

function LinkedList() {

    /**
     * 数据节点构造函数
     *
     * @param {*} data
     */
    function Node(data) {
        this.data = data;
        this.next = null;
    }

    let length = 0;

    let head = null;
    let tail = null;

    /**
     * 链表尾部追加数据
     *
     * @param {*} item
     */
    this.append = function (item) {

        const newNode = new Node(item);

        if (0 < length) {
            tail.next = newNode;
            tail = newNode;
        } else {
            head = tail = newNode;
        }

        length++;

    };

    /**
     * 在指定索引位置的前面插入数据
     *
     * @param {number} index 指定的索引位置
     * @param {*} item
     * @returns {boolean} 返回是否成功
     */
    this.insert = function (index, item) {

        if (0 <= index && index <= length) {

            const newNode = new Node(item);

            if (0 < index && index < length) {

                // 在中间添加
                let prevNode = null;
                let targetNode = head;

                let prevIndex = 0;
                while ((prevIndex++) < index) {
                    prevNode = targetNode;
                    targetNode = targetNode.next;
                }

                prevNode.next = newNode;
                newNode.next = targetNode;

            } else if (0 === index) {

                // 在头部添加
                newNode.next = head;
                head = newNode;

            } else {

                // 在尾部添加
                this.append(item);

            }

            length++;

            return true;

        } else {

            return false;

        }

    };

    /**
     * 删除指定索引位置处的数据项。发生错误将throw一个Error
     *
     * @param {number} index 指定的索引位置
     * @returns {*} 返回被删除的数据
     */
    this.remove = function (index) {

        if (0 <= index && index < length) {

            let targetNode;

            if (0 < index) {

                // 删除非头部
                let prevNode = null;
                targetNode = head;

                let prevIndex = 0;
                while ((prevIndex++) < index) {
                    prevNode = targetNode;
                    targetNode = targetNode.next;
                }

                prevNode.next = targetNode.next;
                targetNode.next = null;

                // 如果删除的是最后一个,把tail指向倒数第二个
                if ((1 + index) === length) {
                    tail = prevNode;
                }

            } else if (0 === index) {

                targetNode = head;

                // 删除头部
                const nextNode = targetNode.next;
                targetNode.next = null;

                head = nextNode;

            }

            length--;

            return targetNode.data;

        } else {

            throw new RangeError(`out of range: must between 0 and ${length}`);

        }

    };

    /**
     * 查找数据项在链表中的索引位置
     *
     * @param {*} item
     * @returns {number} 索引位置,不存在则返回-1
     */
    this.indexOf = function (item) {

        let prevIndex = 0;

        let targetNode = head;
        while (!!targetNode) {
            if (item !== targetNode.data) {
                targetNode = targetNode.next;
                prevIndex++;
            } else {
                return prevIndex;
            }
        }

        return -1;

    };

    /**
     * 顺序打印出链表中的所有节点数据
     *
     */
    this.print = function () {

        let index = 0;

        let targetNode = head;
        while (!!targetNode) {
            console.log('[', index++, ']=>', targetNode.data);
            targetNode = targetNode.next;
        }

    };

    /**
     * 查找单链表中的第K个节点
     *
     * @param {number} index 索引位置
     * @returns {*} index位置的数据
     */
    this.findByIndex = function (index) {

        if (0 <= index && index < length) {

            let targetNode = head;
            while (0 < (index--)) {
                targetNode = targetNode.next;
            }

            return targetNode.data;

        } else {
            throw new RangeError(`out of range: must between 0 and ${length}`);
        }

    };

    /**
     * 查找单链表的中间位置的节点
     *
     * @returns {*} index位置的数据
     */
    this.findMiddle = function () {

        const index = Math.round(length / 2) - 1;

        return this.findByIndex(index);

    };

}

二、实现双向链表的构造函数

function DoubleLinkedList() {
    let length=0,
        head=null,
        tail=null;


    /**
     * 数据节点构造函数
     *
     * @param {*} data
     */
    function Node(data) {

        this.data=data;
        this.next=null;
        this.previous=null;
    }

    /**
     * 链表尾部追加数据
     *
     * @param {*} item
     */
    this.append = function (item) {
        let newNode=new Node(item);
        //空链表
        if(null===head){
            head=newNode;
            tail=head;
        }else{
            tail.next=newNode;
            tail=newNode;
        }
        length++;
    };

    /**
     * 在指定索引位置的前面插入数据
     *
     * @param {number} index 指定的索引位置
     * @param {*} item
     */
    this.insert = function (index, item) {
        let newNode=new Node(item),
            current=head,
            previous=null,
            insetIndex=0;

        if(index < 0 || index > length){
            return false
        }else {
            //在第一个位置添加
            if(0 === index){
                newNode.next=current;
                current.previous=newNode;
                head=newNode
            }else if(index === index){
                //在末尾添加
                current=tail;
                current.next=newNode;
                newNode.previous=current;
                tail=newNode;
            }else {

                while (insetIndex < index){
                    previous=current;
                    current=current.next;
                    insetIndex++;
                }
                previous.next=newNode;
                newNode.previous=previous;
                newNode.next=current;
                current.previous=newNode;

            }
            length++;

        }
    };

    /**
     * 删除指定索引位置处的数据项
     *
     * @param {number} index 指定的索引位置
     */
    this.remove = function (index) {
        if (0 <= index && index < length) {
            let targetNode;
            if (0 < index) {
                // 删除非头部
                let prevNode = null;
                targetNode = head;
                let prevIndex = 0;
                while ((prevIndex++) < index) {
                    prevNode = targetNode;
                    targetNode = targetNode.next;
                }
                prevNode.next = targetNode.next;
                if (!!targetNode.next) {
                    targetNode.next.prev = prevNode;
                }
                targetNode.prev = null;
                targetNode.next = null;
                // 如果删除的是最后一个,把tail指向倒数第二个
                if ((1 + index) === length) {
                    tail = prevNode;
                }
            } else if (0 === index) {
                targetNode = head;
               // 删除头部
                const nextNode = targetNode.next;
                nextNode.prev = null;
                head = nextNode;
                targetNode.next = null;
            }
            length--;
            return targetNode.data;

        } else {

            throw new RangeError(`out of range: must between 0 and ${length}`);
        }
    };
    /**
     * 顺序打印出链表中的所有节点数据
     *
     */
     this.print = function () {

        console.log('顺序打印');

        let index = 0;

        let targetNode = head;
        while (!!targetNode) {
            console.log('[', index++, ']=>', targetNode.data);
            targetNode = targetNode.next;
        }

    };

    /**
     * 逆序打印出链表中的所有节点数据
     *
     */
     this.reversePrint = function () {

        console.log('逆序打印');

        let index = length - 1;

        let targetNode = tail;
        while (!!targetNode) {
            console.log('[', index--, ']=>', targetNode.data);
            targetNode = targetNode.prev;
        }

    };
}

猜你喜欢

转载自blog.csdn.net/wf00334814/article/details/83216200