基础知识就像是一座大楼的地基,它决定了我们的技术高度。
我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一。
栈、队列、链表、堆 是数据结构与算法中的基础知识,是程序员的地基。
笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习。
1. 线性表与非线性表线性表(Linear List):就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。数组、链表、队列、栈 等就是线性表结构。
非线性表:数据之间并不是简单的前后关系。二叉树、堆、图 就是非线性表。
本文主要讲线性表,非线性表会在后面章节讲。
2. 数组 定义数组 (Array) 是一个有序的数据集合,我们可以通过数组名称 (name) 和索引 (index) 进行访问。
数组的索引是从 0 开始的。
特点数组是用一组连续的内存空间来存储的。
所以数组支持 随机访问,根据下标随机访问的时间复杂度为 O(1)。
低效的插入和删除。
数组为了保持内存数据的连续性,会导致插入、删除这两个操作比较低效,因为底层通常是要进行大量的数据搬移来保持数据的连续性。
插入与删除的时间复杂度如下:
插入:从最好 O(1) ,最坏 O(n) ,平均 O(n)
删除:从最好 O(1) ,最坏 O(n) ,平均 O(n)
但是因为 JavaScript 是弱类型的语言,弱类型则允许隐式类型转换。
隐式:是指源码中没有明显的类型转换代码。也就是说,一个变量,可以赋值字符串,也可以赋值数值。
let str = "string" str = 123 console.log(str) // 123你还可以直接让字符串类型的变量和数值类型的变量相加,虽然得出的最终结果未必是你想象的那样,但一定不会报错。
let a = 123 let b = "456" let c = a + b // 数值加字符串,结果是字符串 console.log(c) // "123456"数组的每一项可以是不同的类型,比如:
// 数组的类型有 数值、字符串,还可以随意变更类型 const arr = [ 12, 34, "abc" ] arr[2] = { "key": "value" } // 把数组的第二项变成对象 console.log(arr) // [ 12, 34, { "key": "value"} ]定义的数组的大小是可变的,不像强类型语言,定义某个数组变量的时候就要定义该变量的大小。
const arr = [ 12, 34, "abc"] arr.push({ "key": "value" }) // 添加一项 对象 consolelog(arr) // [ 12, 34, "abc", { "key": "value" } ] 实现JavaScript 原生支持数组,而且提供了很多操作方法,这里不展开讲。
3. 栈 定义后进者先出,先进者后出,简称 后进先出(LIFO),这就是典型的栈结构。
新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另一端就叫栈底。
在栈里,新元素都靠近栈顶,旧元素都接近栈底。
从栈的操作特性来看,是一种 操作受限的线性表,只允许在一端插入和删除数据。
不包含任何元素的栈称为空栈。
栈也被用在编程语言的编译器和内存中保存变量、方法调用等,比如函数的调用栈。
实现栈的方法:
push(element):添加一个(或几个)新元素到栈顶。
pop():移除栈顶的元素,同时返回被移除的元素。
peek():返回栈顶的元素,不对栈做任何修改。
isEmpty():如果栈里没有任何元素就返回 true,否则返回 false。
clear():移除栈里的所有元素。
size():返回栈里的元素个数。
// Stack类 function Stack() { this.items = []; // 添加新元素到栈顶 this.push = function(element) { this.items.push(element); }; // 移除栈顶元素,同时返回被移除的元素 this.pop = function() { return this.items.pop(); }; // 查看栈顶元素 this.peek = function() { return this.items[this.items.length - 1]; }; // 判断是否为空栈 this.isEmpty = function() { return this.items.length === 0; }; // 清空栈 this.clear = function() { this.items = []; }; // 查询栈的长度 this.size = function() { return this.items.length; }; // 打印栈里的元素 this.print = function() { console.log(this.items.toString()); }; }