数据结构与算法(一)之数组,队列,栈(偏向JS)

数据结构(一)

说明:本文基于哔哩哔哩视频【JavaScript数据结构与算法】整理

一、基本概念:

数据的组织方式

二、生活中的实例:

图书的摆放,快递分发

三、常见的数据结构
注意事项
  • (操作性能不同:查询速度、插入、范围查找、重复性)
  • ※ ※※ ※ ※ 是重点,每个编程语言都提供的数据类型
  • JS 是API的使用者,对数据结构接触不多;
数组(Array) ※ ※ ※ ※ ※
  • 线性结构 查找性能较高(利用下标,有序)或者较低(基于内容)插入效率低

  • 操作:

  • 长度

  • 增删改查(splice)

  • 索引(indexOf/lastIndexOf)

  • 数组合并(cancat)

  • 迭代(every,some,forEach,filter,map,reduce【较难,用于函数编程】)

  • 倒序(reverse)

  • 截取(slice)

  • 排序(sort)

  • 转为字符串(toString/valueOf);

  • 缺点:需要一整块连续的内存空间,插入和删除需要大量的位移,成本较高。

  • 操作的代码实现

        var arr = [1, 2, 3, 4, 5]
        var arr1 = new Array() // 效率低
        arr1 = ['q', 'w', 'e']
            // 数组的长度
        console.log(arr.length);

        // 数组的遍历
        arr.forEach((item, i) => {
            console.log(item == arr[i]);
        });
        // 数组元素插入
        arr.splice(2, 0, 'a', 'b') // [1, 2, "a", "b", 3, 4, 5] "插入"
        console.log(arr, '插入');

        // 删除
        arr.splice(1, 3)
        console.log(arr, '删除'); // [1, 3, 4, 5] "删除"
        // 修改
        arr.splice(1, 1, '1123456', 'gh')
        console.log(arr, '修改'); // [1, "1123456", "gh", "a", "b", 3, 4, 5] "删除"
        // 获取
        console.log(arr[0]); // 1

        // 拼接数组
        var arrC = arr.concat(arr1)
        console.log(arrC, '拼接数组'); //  [1, "1123456", "gh", 4, 5, "q", "w", "e"] "拼接数组"

        // 拼接 返回字符串
        // var arrJ = arr.join(',')
        // console.log(arrJ, '==join'); // 1,1123456,gh,4,5 ==join

        // 转化为字符串
        console.log(arr.toString(), '转化为字符串 toString'); //  1,1123456,gh,4,5
        console.log(arr.valueOf(3), '转化 value of'); //  [1, "1123456", "gh", 4, 5]    value.valueOf()  返回value 的原始值


        // 数组的迭代
        // every,some(判断数组中是不是包含某一项或者所有项)
        let flag = arr.every(item => {
            // console.log(item, 'item');

            return item.toString().indexOf('1') != -1
        })
        console.log(flag, '迭代 every'); // every=>false     some=> true


        //filter   map
        let arrF = arr.filter(item => {
            return item.toString().indexOf('1') != -1
        })
        console.log(arrF, '迭代 filter'); // [1, "1123456"]

        let arrMap = arr.map(item => {
            return item + " &"
        })
        console.log(arrMap, '迭代 map'); //  ["1 &", "1123456 &", "gh &", "4 &", "5 &"]


        // arr.reduce(callback[, initialValue])
        let arrReduce = arr.reduce((pre, cur) => {
            return pre + ',' + cur
        })
        console.log(arrReduce, '迭代 reduce'); // 1,1123456,gh,4,5
        //  优势在于reduce方法有返回值, 而forEach没有   【 函数式编程 】
队列(queue)
  • 基于数组

  • 受限的线性结构 从前端删除,从后端插入(先进先出【 FIFO 】:FIRST IN FIRST OUT

  • 生活实例:排队;

  • 程序中的应用:打印机的打印队列;线程队列;

  • 栈结构的实现方式:

  • 基于数组 栈中存放数组。代码实现。

  • 基于链表

    具体操作
  • enqueue(element):向队列尾部添加一个(或多个)新的项。

  • dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。shift 删除第一个

  • front():返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。

  • isEmpty():如果队列中不包含任何元素,返回true,否则返回false。

  • size():返回队列包含的元素个数,与数组的length属性类似

  • 操作的代码实现

// 受限的线性结构
        function Queue(params) {
            // 属性
            this.items = [];
            // 方法
            //  enqueue(element):向队列尾部添加一个(或多个)新的项。
            Queue.prototype.enqueue = function(ele) {
                this.items.push(ele);
            };
            // dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。
            Queue.prototype.dequeue = function() {
                return this.items.shift();
            };
            // front():返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。
            Queue.prototype.front = function() {
                return this.items[0];
            };
            // isEmpty():如果队列中不包含任何元素,返回true,否则返回false。
            Queue.prototype.isEmpty = function() {
                return this.items.length === 0;
            };
            // size():返回队列包含的元素个数,与数组的length属性类似
            Queue.prototype.size = function() {
                return this.items.length;
            };
            // return this.items
        }
  • 击鼓传花案例
  // 实现击鼓传花的函数
        function passGame(nameList, num) {
            // 1.创建一个队列, 并且将所有的人放在队列中
            // 1.1.创建队列
            var queue = new Queue();

            // 1.2.通过for循环, 将nameList中的人放在队列中
            for (var i = 0; i < nameList.length; i++) {
                queue.enqueue(nameList[i]);
            }

            // 2.寻找最后剩下的人
            while (queue.size() > 1) {
                // 将前num-1中的人, 都从队列的前端取出放在队列的后端
                for (var i = 0; i < num; i++) {
                    queue.enqueue(queue.dequeue());
                }

                // 将第num个人, 从队列中移除
                queue.dequeue();
            }

            // 3.获取剩下的一个人
            alert(queue.size());
            var endName = queue.dequeue();
            alert("最终留下来的人:" + endName);

            // 4.获取该人在队列中的位置
            return nameList.indexOf(endName);
        }
*** 优先级队列(有特权,可以插队的队列)。
		// 封装优先级队列
        function PriorityQueue() {
            var items = [];

            // 封装一个新的构造函数, 用于保存元素和元素的优先级
            function QueueElement(element, priority) {
                this.element = element;
                this.priority = priority;
            }

            // 添加元素的方法
            this.enqueue = function(element, priority) {
                // 1.根据传入的元素, 创建新的QueueElement
                var queueElement = new QueueElement(element, priority);

                // 2.获取传入元素应该在正确的位置
                if (this.isEmpty()) {
                    items.push(queueElement);
                } else {
                    var added = false;
                    for (var i = 0; i < items.length; i++) {
                        // 注意: 我们这里是数字越小, 优先级越高
                        if (queueElement.priority < items[i].priority) {
                            items.splice(i, 0, queueElement);
                            added = true;
                            break;
                        }
                    }

                    // 遍历完所有的元素, 优先级都大于新插入的元素时, 就插入到最后
                    if (!added) {
                        items.push(queueElement);
                    }
                }
            };

            // 删除元素的方法
            this.dequeue = function() {
                return items.shift();
            };

            // 获取前端的元素
            this.front = function() {
                return items[0];
            };

            // 查看元素是否为空
            this.isEmpty = function() {
                return items.length == 0;
            };

            // 获取元素的个数
            this.size = function() {
                return items.length;
            };
        }
栈(stack)
  • 基于数组

  • 受限的线性结构

  • 插入或者删除位置只能在栈顶

  • 进栈出栈(后进先出【 LIFO 】:因为只能在栈顶进或者出)
    在这里插入图片描述

  • 生活实例:盘子叠放拿取, 程序中的应用:函数调用栈(A=调用==>B调用>C),C 最早被调用;递归; 十进制转二进制

  • 面试题:654321的顺序进栈,选出下列不能实现的出栈顺序 A、543612 B、453216 C、346521 D、234156

  • 栈结构的实现方式:

  • 基于数组 栈中存放数组。代码实现(见下方)。

  • 基于链表

  • 常用的操作:

  • push(element): 添加一个新元素到栈顶位置.

  • pop():移除栈顶的元素,同时返回被移除的元素。删除最后一个

  • peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。

  • isEmpty():如果栈里没有任何元素就返回true,否则返回false。 clear():移除栈里的所有元素。

  • size():返回栈里的元素个数。这个方法和数组的length属性很类似。

  • 代码实现

// 栈结构的封装
		function Stack() {
            // 栈的属性
            var items = []; //基于数组实现

            // 栈的操作
            // push(element): 添加一个新元素到栈顶位置.   // 压栈操作
            Stack.prototype.push = function(ele) {
                // console.log(this, 'this');
                items.push(ele);
            };

            // pop():移除栈顶的元素,同时返回被移除的元素。  // 出栈
            Stack.prototype.pop = function() {
                items.pop();
            };

            // peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。
            Stack.prototype.peek = function() {
                console.log(items, "item");

                return items[items.length - 1];
            };
            // isEmpty():如果栈里没有任何元素就返回true,否则返回false。
            Stack.prototype.isEmpty = function() {
                return items.length === 0;
            };

            // size():返回栈里的元素个数。这个方法和数组的length属性很类似。
            Stack.prototype.size = function() {
                return items.length;
            };

            // clear():移除栈里的所有元素。
            Stack.prototype.clear = function() {
                return items = [];
            };

            // toString():栈里的所有元素转化为字符。
            Stack.prototype.toString = function() {
                let res = "";
                items.forEach((item) => {
                    res += item + " ";
                });
                return res;
            };

        }

其他数据结构可访问以下地址:
数据结构与算法(二)之单向链表和双向链表(偏向JS)
数据结构与算法(三)之集合,字典(偏向JS).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值