JavaScript数据结构与算法(个人学习笔记)

一、栈的封装

栈:先进后出

        // method方法 和某个对象实例有联系
        function Stack() {
            this.items = [] //栈中的属性
            // 压入栈
            // this.push = function() { //方法
            // }
            Stack.prototype.push = function (element) {
                this.items.push(element)
            }
            // 取出元素
            Stack.prototype.pop = function () {
                return this.items.pop()
            }
            // 查看元素
            Stack.prototype.peek = function () {
                return this.items[this.length - 1]
            }
            // 判断栈是否为空
            Stack.prototype.isEmpty = function () {
                return this.items.length == 0
            }
            // 获取栈中元素的个数
            Stack.prototype.size = function () {
                return this.items.length
            }
            // toString方法
            Stack.prototype.toString = function () {
                for (var i = 0; i < this.items.length; i++) {
                    resultString += this.items[i] + ''
                }
                return resultString
            }
        }
        // var s = new Stack()

        // s.push(22)
        // console.log(s.isEmpty());

    
        function decbin2(decNumber) {
            var  stack = new Stack()   
            while(decNumber > 0) {
                stack.push(decNumber % 2)
                decNumber = Math.floor(decNumber / 2)
            }

            var binaryString = ''
            while(!stack.isEmpty()) {
                binaryString += stack.pop()
            }

            return binaryString
        }
        alert(decbin2(100))

二、队列的封装

先进先出

function Queue() {
            this.items = []
            // 加入队列
            Queue.prototype.enqueue = function (element) {
                this.items.push(element)
            }
            // 删除前端口元素
            Queue.prototype.dequeue = function () {
                return this.items.shift()
            }
            // 查看前端的元素
            Queue.prototype.front = function () {
                return this.items[0]
            }
            // 查看队列中元素是否为空
            Queue.prototype.isEmpty = function () {
                return this.items.length == 0
            }
            // 查看队列中元素的个数
            Queue.prototype.size = function () {
                return this.items.length
            }
            // toString方法
            Queue.prototype.toString = function () {
                var resultString = ''
                for (let i = 0; i < this.items.length; i++) {
                    resultString += this.items[i] + ' '
                }
                return resultString
            }
        }
        // var Queue = new Queue()

        // Queue.enqueue('acb')
        // Queue.enqueue('sdf')
        // Queue.enqueue('edc')
        // alert(Queue)
        // Queue.dequeue()
        // alert(Queue.front())
        // alert(Queue.isEmpty())
        // alert(Queue.toString())

        // 队列应用之击鼓传花
        function flower(nameList, num) {
            var queue = new Queue()
            // 将所有人一次加入队列
            for (var i = 0; i < nameList.length; i++) {
                queue.enqueue(nameList[i])
            }
            // 开始数数字
            while (queue.size() > 1) {
                for (var i = 0; i < num - 1; i++) {
                    queue.enqueue(queue.dequeue())
                }
                queue.dequeue()
            }

            // 获取最后剩下的那个人
           alert(queue.size()) // kankan最后是不是队列是不是只有一个元素
            console.log(queue.front());
            var endName = queue.front()
            alert('最后一个人是: ' + endName)

            return nameList.indexOf(endName)
        }
        names = ['lili', 'haha', 'xixi', 'leilei']
        alert(flower(names, 3))

三、优先级队列的封装

 function PriortyQueue() {
            // 类新创建一个类 可理解成内部内
            function QueueElement(element, priorty) {
                this.element = element
                this.priorty = priorty
            }

            this.items = [] //封装属性
            PriortyQueue.prototype.enqueue = function (element, priorty) {
                var queueElement = new QueueElement(element, priorty)
                // 判断队列是否为空
                if (this.items.length == 0) {
                    this.items.push(queueElement)
                } else {
                    var added = false
                    for (var i = 0; i < this.items.length; i++) {
                        if (queueElement.priorty < this.items[i].priorty) {
                            this.items.splice(i, 0, queueElement)
                            added = true
                            break
                        }
                    }
                    if (!added) {
                        this.items.push(queueElement)
                    }
                }
            }
            // 删除前端口元素
            PriortyQueue.prototype.dequeue = function () {
                return this.items.shift()
            }
            // 查看前端的元素
            PriortyQueue.prototype.front = function () {
                return this.items[0]
            }
            // 查看队列中元素是否为空
            PriortyQueue.prototype.isEmpty = function () {
                return this.items.length == 0
            }
            // 查看队列中元素的个数
            PriortyQueue.prototype.size = function () {
                return this.items.length
            }
            // toString方法
            PriortyQueue.prototype.toString = function () {
                var resultString = ''
                for (let i = 0; i < this.items.length; i++) {
                    resultString += this.items[i].element  + this.items[i].priorty + ''
                }
                return resultString
            }
        }

        var pq = new PriortyQueue()

        pq.enqueue('abc', 1)
        pq.enqueue('wsx', 2)
        pq.enqueue('qqq', 1000)
        pq.enqueue('edc', 3)
        alert(pq)

四、链表的封装

 //单向链表
        function LinkedList() {
            //结点类
            function Node(data) {
                this.data = data
                this.next = null
            }
            this.head = null
            this.length = 0 //计算链表的长度

            // 1. 添加
            LinkedList.prototype.append = function (data) {
                var newNode = new Node(data) //新建新的结点
                if (this.length == 0) {
                    this.head = newNode
                } else {
                    var current = this.head
                    while (current.next) {
                        current = current.next
                    }
                    current.next = newNode // 最后结点的next指向新的结点
                }
                this.length += 1
            }

            // 2.toString
            LinkedList.prototype.toString = function () {
                var current = this.head
                var listString = ''
                while (current) {
                    listString += current.data + " "
                    current = current.next
                }
                return listString
            }

            // 3.insert
            LinkedList.prototype.insert = function (position, data) {
                // 对position进行边界判断
                if (position < 0 || position > this.length) return false
                var newNode = new Node(data)
                if (position == 0) {
                    newNode.next = this.head
                    this.head = newNode
                } else {
                    var index = 0
                    var current = this.head
                    var previous = null
                    while (index++ < position) {
                        previous = current
                        current = current.next
                    }
                    newNode.next = current
                    previous.next = newNode
                }
                this.length += 1
                return true
            }

            // 4.get 获取对应位置
            LinkedList.prototype.get = function (position) {
                if (position < 0 || position >= this.length) return null
                var current = this.head
                var index = 0
                while (index <= position) {
                    current = current.next
                    index++
                }
                return current.data
            }
            // 5.indexOf返回该元素在该链表中的索引
            LinkedList.prototype.indexOf = function (data) {
                var current = this.head
                var index = 0
                while(current) {
                    if(current.data == data) {
                        return index
                    }
                    current = current.next
                    index ++
                }
                return -1
            }

            // 6.update修改某一位置的数值
            LinkedList.prototype.update = function (position, newData) {
                if (position < 0 || position >= this.length) return null
                var current = this.head
                var index = 0
                while(index++ < position) {
                    current = current.next
                }
                current.data = newData
                return true
            }

            // 7.removeAt 从列表中移除一项
            LinkedList.prototype.removeAt = function(position) {
                if (position < 0 || position >= this.length) return null
                if(position == 0) {
                    this.head = this.head.next
                } else {
                    var current = this.head
                    var index = 0
                    var previous = null
                    while(index++ < position) {
                        previous = current
                        current = current.next
                    }
                    // 前一个结点的next指向current的next
                    previous.next = current.next
                }
                this.length -= 1
                return current.data
            }
            // 8.remove
            LinkedList.prototype.remove = function(data) {
                //根据data获取位置
                var position = this.indexOf(data)
                //根据位置移除元素
                return this.removeAt(position)
            }
            // 9.isEmpty
            LinkedList.prototype.isEmpty = function () {
                return this.length==0
            }
            // 10.size
            LinkedList.prototype.size = function () {
                return this.length
            }
        }


        var list = new LinkedList()
        list.append('ddd')
        list.append('bbbb')
        list.append('ccc')
        list.insert('1', 'wsx')
        list.update('2','ooo')
        list.removeAt(1)
        alert(list)
        alert(list.get(1))
        alert(list.indexOf('ddd'))
        alert(list.isEmpty())
        alert(list.size())

五、双向链表的封装

function LinkedList() {
            // 内部类
            function Node(data) {
                this.data = data
                this.next = null
                this.prev = null // 新添加的
            }
            this.head = null;
            this.tail = null;
            this.length = 0;


            // 向链表尾部加一个
            LinkedList.prototype.append = function (data) {
                // 1.根据元素创建节点
                var newNode = new Node(data)

                // 2.判断列表是否为空列表
                if (this.length == 0) {
                    this.head = newNode
                    this.tail = newNode
                } else {
                    newNode.prev = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode;
                }

                // 3.length+1
                this.length++

            }

            // 链表转化为字符串
            LinkedList.prototype.toString = function () {
                return this.forwardString();
            }
            // 向前遍历
            LinkedList.prototype.forwardString = function () {
                var current = this.head
                var forwardStr = ""

                while (current) {
                    forwardStr += "," + current.data
                    current = current.next
                }

                return forwardStr.slice(1)
            }
            // 向后遍历
            LinkedList.prototype.reverseString = function () {
                var current = this.tail
                var reverseStr = ""

                while (current) {
                    reverseStr += current.data + " "
                    current = current.prev
                }
                return reverseStr
            }

            // 插入
            LinkedList.prototype.insert = function (position, data) {
                if (position < 0 || position > this.length) return false;
                var newNode = new Node(data);
                if (this.length == 0) {
                    this.head = newNode;
                    this.tail = newNode;
                } else {
                    if (position == 0) { // 插入到第一个结点
                        this.head.prev = newNode;
                        newNode.next = this.head;
                        this.head = newNode;
                    } else if (position == this.length) { // 插入最后一个结点
                        newNode.prev = this.tail;
                        this.tail.next = newNode;
                        this.tail = newNode;
                    } else {
                        var current = this.head;
                        var index = 0;
                        while (index < position) {
                            current = current.next
                            index++
                        }
                        newNode.next = current;
                        newNode.prev = current.prev;
                        current.prev.next = newNode;
                        current.prev = newNode;
                    }
                }
                this.length++
                return true
            }

            // 获取对应位置的值
            LinkedList.prototype.get = function (position) {
                if (position < 0 || position >= this.length) return null
                // 效率不高
                // var current = this.head;
                // var index = 0;
                // while(index ++ < position) {
                //     current = current.next
                // }
                // return current.data

                if (this.length / 2 > position) {
                    let current = this.head;
                    let index = 0;
                    while (index++ < position) {
                        current = current.next
                    }
                    return current.data
                } else {
                    let current = this.tail;
                    let index = this.length - 1;
                    while (index-- > position) {
                        current = current.prev
                    }
                    return current.data
                }
            }

            // 返回对应位置的索引
            LinkedList.prototype.indexOf = function (data) {
                var current = this.head;
                var index = 0
                while (current) {
                    if(current.data == data) {
                        return index
                    }
                    current = current.next;
                    index ++
                }
                return -1
            }

            // 更新元素
            LinkedList.prototype.update = function (position, data) {
                if(position < 0 || position >= this.length) return false;
                var current = this.head;
                var index = 0;
                while (index++ < position) {
                    current = current.next
                }
                current.data = data
                return true
            }
            // 从列表的特定位置移除一项
            LinkedList.prototype.removeAt = function (position) {
                if(position < 0 || position >= this.length) return false;
                var current = this.head;
                if(this.length == 1) {
                    this.head = null;
                    this.tail = null;
                } else {
                    if (position == 0) {
                        this.head.next.prev = null;
                        this.head = this.head.next;
                    } else if (position == this.length - 1) {
                        current = this.tail;
                        this.tail.prev.next = null;
                        this.tail = this.tail.prev;
                    } else {
                        var index = 0;
                        while(index++ < position) {
                            current = current.next
                        }
                        current.prev.next = current.next
                        current.next.prev = current.prev
                        current.prev = null
                    }
                }
                this.length -= 1
                return current.data
            }
            // 移除元素
            LinkedList.prototype.remove = function (data) {
                var index = this.indexOf(data)
                return this.removeAt(index)
            }

            //是否为空
            LinkedList.prototype.isEmpty = function() {
                return this.length == 0 
            } 

            // 长度
            LinkedList.prototype.size = function () {
                return this.length
            }

            // 获取链表的第一个元素
            LinkedList.prototype.getHead = function() {
                return this.head.data
            }
            
            // 获取链表的最后一个元素
            LinkedList.prototype.getTail = function() {
                return this.tail.data
            }
            
        }

        // 测试
        var list = new LinkedList()
        list.append("abc")
        list.append("cba")
        list.append("nba")
        list.append("mba")
        list.insert(2, "aaa")
        // alert(list.reverseString())
        // alert(list.forwardString())
        // alert(list)
        // alert(list.get(4))
        // alert(list.indexOf('aaa'))
        // alert(list.indexOf('111'))
        // list.update(2, 'ccc')
        // alert(list.removeAt(1))
        // list.remove('aaa')
        alert(list.isEmpty())
        alert(list.size())
        alert(list.getHead())
        alert(list.getTail())
        alert(list)

六、集合的封装

// 和数学中集合名词相似,但是属性中结合范围更大,允许元素重复
        // 在计算机中,集合通常表示的结构的元素是不允许重复的
        // 可以看做特殊的数组 特殊之处在于没有顺序(所以不能通过下标直接访问),也没有重复
        // 就是ES6的Set1类
        function Set1() {
            // 属性
            this.items = {}
            // 方法
            Set1.prototype.add = function (value) {
                // 判断集合中是否包含该元素
                if (this.has(value)) {
                    return false
                }
                this.items[value] = value
                return true
            }
            Set1.prototype.has = function (value) {
                return this.items.hasOwnProperty(value)
            }
            Set1.prototype.remove = function (value) {
                if (!this.has(value)) {
                    return false
                }
                delete this.items[value]
                return true
            }
            Set1.prototype.clear = function () {
                this.items = {}
            }
            Set1.prototype.size = function () {
                return Object.keys(this.items).length //妙a
            }
            Set1.prototype.values = function () {
                return Object.values(this.items)
            }
            // 集合间的操作
            // 并集
            Set1.prototype.union = function (otherSet) {
                // this集合对象A otherSet集合对象B
                // 1.创建新的集合
                var unionSet = new Set1()
                // 2.将A集合中的所有元素添加到新集合中
                var values = this.values()
                for (var i = 0; i < values.length; i++) {
                    unionSet.add(values[i])
                }
                // 3.取出B集合中的元素,判断是否需要加到新集合
                values = otherSet.values()
                for(var i = 0; i < values.length; i++) {
                    unionSet.add(values[i])
                }
                return unionSet
            }

            // 交集
            Set1.prototype.insertsection = function (otherSet) {
                var insertsection = new Set1()
                // 从A中取出一个元素,判断是否同时存在集合B中,存放人新集合中
                var values = this.values()
                for(var i = 0; i < values.length; i++) {
                    var item = values[i]
                    if(otherSet.has(item)) {
                        insertsection.add(item)
                    }
                }
                return insertsection
            }

            // 差集
            Set1.prototype.difference = function (otherSet) {
                var differenceSet = new Set1()
                var values = this.values()
                for(var i = 0; i < values.length; i++) {
                    var item = values[i]
                    console.log(item);
                    if (!otherSet.has(item)) {
                        differenceSet.add(item)
                    }
                }
                return differenceSet
            }

            // 子集
            Set1.prototype.subSet = function (otherSet) {
                var values = this.values()
                for (var i = 0; i < values.length; i++) {
                    var item = values[i]
                    if(!otherSet.has(item)) {
                        return false
                    } 
                }
                return true
            }
        }

        var set1 = new Set1()
        set1.add("1")
        set1.add("1")
        set1.add("2")
        set1.add("aaaa")
        set1.add('b')
        set1.remove(1)
        // alert(set1.size())
        // alert(set1.values())
        // alert(set1.size())

        var setA = new Set1()
        setA.add('abc')
        setA.add('qaz')
        setA.add('iop')
        var setB = new Set1()
        setB.add('qwe')
        setB.add('rfv')
        setB.add('iop')
        var setC = new Set1()
        setC.add('qwe')
        setC.add('rfv')
        setC.add('iop')
        
        // alert(setA.union(setB).values())

        // alert(setA.insertsection(setB).values())

        // alert(setA.difference(setB).values())
        alert(setA.subSet(setB))
        alert(setC.subSet(setB))

七、字典

字典的主要特点是一一对应的关系,通过键值对进行保存;字典的可以是不可以重复的,而value可以重复,并且字典中的可以是无序的。
在这里插入图片描述

八、哈希表

数组进行插入删除操作时,效率比较低;数组进行查找操作的效率:如果是基于索引查找进行查找效率非常高,基于内容查找比较低。
哈希表通常基于数组进行实现的,可以非常快速的插入删除查找(时间复杂度接近O(1)),通常哈希表中是不允许重复的,不能放置相同的key,用于保存不同的元素单数。但是哈希表的数据是无序的,所以不能以一种固定的方式(如从小到大)来遍历数据。
在这里插入图片描述
通过哈希化的下标值依然可能重复,冲突不可避免,常见有链地址法(拉链法)、开放地址法两种方案。

  • 链地址法解决冲突的办法是每个数组单元中存储的不再是单个数据,二十一个链条,这个链条常用的数据结构是数组或链表。
  • 开放地址发主要的工作方式是寻找空白的单元格来添加重复的数据。
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值