关于JavaScript

本文深入探讨JavaScript中的基础数据结构,重点讲解数组和栈。详细介绍了数组的定义、创建、方法及其扩展,包括二维数组和类型数组的概念。接着讨论栈的原理,通过JavaScript数组实现栈,并展示了如何保护数据结构内部元素。文章还给出了使用栈解决实际问题,如阶乘计算和合法括号判断的示例代码。

1、基础数据结构

1.1数据结构种类

数组

队列和双端队列

链表

集合

字典和散列表

递归

二叉堆和堆排序

在写每个知识点的时候 我自己总结的方式是按照定义>javascript实现方式>对应的方法>算法实现的结构去写的 后面有想法在继续补充

1.2 数组

1.2.1 数组定义

js数组其实就是API的调用 是一种最简单的内存数据结构 数组存储一系列同一种数据类型的值

注:javascript中数组可以保存不同类型的值 但是一般不推荐哈

1.2.2 数组创建

在javascript中有两种创建数组的方式

1.使用Array构造函数
let shuzu=new Array();
注意:括号里面参数可以有参数,若为一个数字,表示该数组的长度,如果为多个数字或者一个(多个)非数字表示的是传递数组中应该包含的值。

2.使用数组字面量
let shuzu=[];

1.2.3 数组方法

添加元素 (首尾)

删除元素(首尾)

1、在数组末尾添加元素

使用push方法
numbers.push(11);

原生的方法:
numbers[numbers.length] = 10;
在Javascript中,数组是可以修改的对象,如果要添加元素,会动态生长,所以直接赋值给数组最后一个空位即可

2、在数组开头插入元素

使用unshift方法
numbers.unshift(10);

3从数组末尾删除元素

使用pop方法;
numbers.pop();

4、数组开头删除元素

使用shif方法
number.shif();

5、任意位置添加或者删除元素

使用splice方法:
splice接受多个参数
number.splice(4.,0,6,4)
第一个参数标识要删除或者插入的元素索引值
第二个参数是删除元素的个数,这个例子我们要添加元素所以第二个删除元素的个数为0.
第三个参数往后,就是我们 要添加到数组里面的值

1.2.4 数组的扩展

二维数组本质上是以数组作为数组元素的数组,即“数组的数组”,
类型说明符 数组名[常量表达式][常量表达式]。二维数组又称为矩阵,
行列数相等的矩阵称为方阵。对称矩阵a[i][j] = a[j][i],
对角矩阵:n阶方阵主对角线外都是零元素

var arr = [[1,2],[‘a’,‘b’]];
console.log(arr[1][0]); //a 第2列第1行所在的元素

1.2.5 javascript常用的数组方法

1、concat(),连接两个或者更多的数组,并返回一个新的数组**
2、ES6:copyWithin(),从数组的指定位置复制元素到数组的指定位置。语法:array.copyWithin(target, start, end)
3、ES6:entries(),返回数组的迭代对象
4、every(),检测数组所有元素是否都符合指定条件,接收一个函数作为参数,用于检测数组中的元素
5、ES6:fill(),将一个固定的值替换数组里面的元素。语法:array.fill(value, start, end)
6、filter(),返回一个数组,里面包含符合条件的元素
7、find(),返回数组中符合条件的第一个元素
8、findIndex(),返回数组中符合条件的第一个元素的所在位置
9、forEach(),数组每个元素都执行一次回调函数
10、ES6:from(),将伪数组转换为真正的数组
11、ES6:includes(),判断数组中是否函数指定的值,如有返回true,否则返回false
12、indexOf(),返回数组中指定元素的位置,如果数组中没有指定的元素则返回-1
13、isArray(),判断一个对象是否为数组,是 返回true,不是 返回false
15、ES6:keys(),从数组创建一个包含数组键的可迭代对象
16、lastIndexOf(),返回指定的元素在数组中最后出现的位置,在数组的后面开始搜索
17、map(),返回一个新数组,数组中的元素是原始数组的元素调用函数之后处理的值
18、pop(),删除数组的最后一个元素,并返回删除的元素
19、push(),在数组后面添加新元素,并返回数组新的长度

20、reduce(),将元素的值计算为一个值,从左到右
21、reduceRight(),将元素的值计算为一个值,从右到左
22、reverse(),反转数组元素的排列顺序
23、shift(),删除并返回数组第一个元素
24、unshift(),向数组的最前面添加新元素,并返回新的数组长度
25、slice(),返回指定的数组元素,第一个参数是开始的位置,第二个是结束位置(不包含结束位置的元素)

26、splice(),添加和删除数组中的元素,第一个参数是要删除的元素的开始位置,第二个参数是要删除的元素的个数。第三个以及以后的参数都是添加到数组中的新元素
27、some(),检测数组中是否含有指定的元素,有的话就返回true,没有就返回false
28、sort(),对数组进行排序,可以接收一个比较函数
29、toString(),将数组转为字符串,并返回结果
30、valueOf(),返回数组对象的原始值

常用的我已经加粗了!!!

1.2.6 类型数组

由于javascript与c和Java等语言不同,javascript数组不是强类型。可以存储任意类型数据
那么如何让javascript的数组也存储单一的数据类型呢?
这个就用到类型数组。
具体语法:

let myArray = new TypedArray(length)
//在实际使用中  把TypedArray换成下面列表中需要的类型

在这里插入图片描述

1.2.7TypeScript中的数组

Typescript中最简单的方法是使用「类型 + 方括号」来表示数组

let fibonacci: number[] = [1, 1, 2, 3, 5];

数组的项中不允许出现其他的类型:
在使用数组方法时,对应增删改查的元素类型必须一致,否则会报错。

详解文章:
TypeScript 数组Array操作

1.3 栈

1.3.1 概述

栈是一种遵从先进后出(LIFO)原则的有序集合。
新添加或待删除的元素都保存在栈的末尾,称作栈顶,另一端就叫栈底。
在栈里,新元素都靠近栈顶,旧元素都接近栈底

用日常生活中的例子:
栈就像我们的衣服口袋,先放进去的东西后取出来,后放进去的东西能先取出来
在这里插入图片描述

栈被用在编程语言的编译器和内存中用于保存变量,方法调用等等,也被用于浏览器历史记录(浏览器的返回按钮)

1.3.2 基于javascript数组创建栈

在javascript中用数组创建一个栈一共7个步骤:

1、先声明一个stack类,用于存放栈
2、向栈中使用push添加元素(只能从栈顶添加)
3、从栈中使用pop方法移除元素(从栈顶移除)
4.查看栈顶元素(peek方法)
5.检查栈是否为空 方法为isEmpty 如果栈为空返回true 否则返回false
6.使用clear方法清空栈元素
7.可以开始使用stack类
经过上面的六步,stack已近具有了栈的特点。

代码实现:

1.3.3 基于javascript对象创建栈

前面我们已经学会使用数组来创建栈了,但在实际的应用中,处理大量数据的时候,需要评估如何使用数据是最高效的,使用数组的时间复杂度为0(n),n代表数组的长度,因为数组是一个有序集合,为了保证元素排序,会占用更多的内存我们需要迭代整个数组直到寻找到目标元素。

由此引出了对象创建栈
对象能直接获取元素,占用较少的内存空间,而且能够按照我们的要求排列数据。

操作步骤一共六步:

1、声明一个stack类
2、向栈中插入元素
3、验证栈是否为空和它的大小
4、从栈中弹出元素
5、查看栈值并将栈清空
6、创建tostring方法

代码实现:

//首先声明一个stack类
class  stack {
	constructor () {
		this.count = 0 ; //使用count来记录栈的大小,也能帮助我们删除和添加元素
		this.items = {};
	}
}
//向栈中加入元素
push(element) {
	this.items[this.count ] = element;
	this.count ++ ;
}
//在js中,对象是键值对的形式表现出来,我们使用count作为items对象的键名,插入的元素则是它的值,插入元素后,我们把count++,以便于下一个变量值插入
//count属性也表示栈的大小,我们可以返回count的size来计算栈的大小
size(){
	return this.count;
}
//验证栈是否为空
isEmpty(){
	return this.count === 0;
}
//查看栈顶的值并将栈清空
peek{
if (this.isEmpty()){
	return unerfined;
}
	return this.items{this.items.length - 1};
}
//清空栈把值变为构造函数的初始值就ok
clear (){
	this.items = {};
	this.count =  0;
}
//也可以使用另外一种方法:
while (!this.isEmpty()){
	this.pop();
}
//创建tostring方法
在前面的数组中没有提string方法,是因为数组内置就有tostring属性,使用对象的时候,就需要我们手动去穿件了
toString () {
	if  (this.isEmpty()){
		return '';
	}
	let objStru=ing = '${this.items[0]}';
	for  (let i = 1 ; i < this.count; i++ ){
		objString = '${objstring},${this.items[i]}';
	}
	return objstring ;
}
//如果栈是空的,返回空值就ok了
//如果不是空的。底部第一个元素作为字符串的初始值,然后迭代整个栈

至此,一个基于对象创建的栈就完成了

1.3.4 保护数据结构内部元素

在我们创建一个栈后,别的同事也可能要使用,我们想保护内部的元素,只允许改变我们暴露的元素,这个时候就提及到了保护数据结构内部元素:
主要有三种方法:

1、下划线命名约定

下划线命名定义
一部分开发者喜欢在javascript中使用下划线命名约定来标记一个属性为私有属性
下划线命名约定实在属性名称之间加一个下划线-,不过这种方法只是一种约定,不能保护数据,看不懂的程序员就gg了

代码实现:

class stack {
	constructor () {
		this._count = 0;
		this._items = {};
	}
}

2、symbol实现类

使用symbol实现类
在es6中规定,symbol是不可变的,可以用作对象的属性

代码实现:

cosnt_items = symbol('stacItems');
class  stack {
	constoructor () {
		this[_items] = [];
	}
	//栈的方法
}

3、使用weakMap实现类

使用weakMap实现类
weakMap就能确保属性私有,weakMap是键值对的存在,键是对象,值是属性。

1.3.5 javascript中用栈解决实际问题

使用栈实现阶乘的递归

使用栈来模拟5!的过程,首先将数字5到1压入栈,然后使用一个循环将数字挨个弹出并连乘
代码实现:

 1 function fact(num) {
 2     var stack=new Stack;
 3     while(num>0){
 4         stack.push(num--);
 5     }
 6     var sum=1;
 7     while(stack.length>0){
 8         sum*=stack.pop;
 9     }
10     return sum;
11 }
12 
13 console.log(fact(5)) //120

1.3.6 合法括号

下面的字符串中包含小括号,请编写一个函数判断字符串中的括号是否合法,所谓合法,就是括号成对出现

sdf(ds(ew(we)re)rwqw)qwrwq		合法
(sd(qwqe)sd(sd))		合法
()()sd()(sd()dw))(		不合法

思路分析
括号存在嵌套关系,也存在并列关系,如果使用数组来存储这些括号,然后再想办法一对一的抵消掉,似乎可行。但是我们无法判断一个左括号对应的是哪一个右括号。在数组的角度思考这个问题,就有些困难。
现在,我们使用栈来解决这个问题
遇到左括号,就把做括号压入栈中
遇到右括号,判断栈是否为空,如果为空则说明没有左括号与之相对应,字符串括号不合法。如果栈不为空,则把栈顶元素移除,这对括号就抵消了。
当for循环结束,如果栈是空的,说明所有的左右括号都抵消了,如果栈力还有元素,则说明缺少右括号,字符串括号不合法。

代码实现:

function is_leagl_brackets(string){
	var stack = new Stack();
	for (var i = 0;i<string.length;i++) {
		var item = string[i];
		// 遇到做括号入栈
		if(item == '('){
			stack.push(item)
		}else if (item == ')'){
		// 遇到右括号,判断栈是否为空
			if(stack.isEmpty()){
				return false
			}else {
				stack.pop() // 弹出左括号
			}
		}
	}
	//  如果栈为空,说明字符串括号合法
	return stack.isEmpty()
}
console.log(is_leagl_brackets('sdf(ds(ew(we)re)rwqw)qwrwq')) // true
console.log(is_leagl_brackets('(sd(qwqe)sd(sd))')) // true
console.log(is_leagl_brackets('()()sd()(sd()dw))(')) // false

实现一个有min方法的栈

供一个min方法,返回栈里的最小的元素,且时间复杂度为O(1)

function MinStack() {
	var data_stack = new Stack();
	var min_stack = new Stack();
	// 用min_stack 记录每次 push 进来的元素之后,栈中的最小值
	this.push = function (item) {
		data_stack.push(item);
		if(min_stack.isEmpty() || item < min_stack.top()){
			min_stack.push(item)
		}else {
			min_stack.push(min_stack.top())
		}
	};
	// 这样,每次pop之后,min_stack 也会将上次栈中的最小值弹出
	this.pop() = function () {
		data_stack.pop()
		min_stack.pop()
	}
	this.min = function () {
		return min_stack.top()
	}
}

实际应用中还有许多,这里我就不挨个列举 了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值