JavaScript数据结构与算法(1)数组,栈,队列

103 阅读4分钟

数据结构与算法

1、数组

数组特性:

  • 1、查找速度很快,可以通过索引快速查找元素。
  • 2、插入,删除操作速度相对较慢。因为插入,删除时需要对该位置后方的所有元素进行位移
  • 3、数组的创建通常需要申请一段连续的内存空间,并且大小是固定的,所以当当前数组不能满足容量需求时,需要扩容(一般情况下hi申请一个更大的数组,比如2倍,然后将原数组中的元素复制过去)

2、栈

栈特性:

  • 1、是一种受限的数据结构,只有一个口进行进栈和出栈,先进后出的原则

image.png

栈的常见操作

  • 1、push():添加一个新元素到栈顶位置
  • 2、pop():移除栈顶元素,同时返回被移除的元素
  • 3、peek():返回栈顶元素,不对栈进行任何修改
  • 4、isEmpty():如果栈没有任何元素返回true,否则返回false
  • 5、size():返回栈里元素个数,与数组的length方法类似
  • 6、toString():将栈结构以字符串的形式返回
  function Stack(){
    // 栈的属性
    this.items = []

    //栈的相关操作
    // 1、将栈元素压入栈
    Stack.prototype.push = function(element){
      this.items.push(element)
    }

    // 2、从栈中取出元素
    Stack.prototype.pop = function(){
      return this.items.pop()
    }

    // 3、查看一下栈顶元素
    Stack.prototype.peek =function(){
      return this.items[this.items.length -1]
    }

    // 4、判断栈是否为空
    Stack.prototype.isEmpty = function(){
      return this.items.length == 0
    }

    // 5、获取栈中元素的个数
    Stack.prototype.size = function(){
      return this.items.length
    }

    // 6、toString方法
    Stack.prototype.toString = function(){
      let result = ''
      for(let i=0; i<this.items.length; i++){
        result += this.items[i] + ' '
      }
      return result
    }
  }

栈的应用(十进制转成二进制)

function dec2bin(decNumber){
    //1.定义栈对象
    let stack = new Stack()

    // 2、循环操作
    while(decNumber > 0){
      //2.1获取余数,压入栈中
      stack.push(decNumber % 2)

      // 2.2获取整除后的结果,作为下一次运行的数字
      decNumber = Math.floor(decNumber / 2)
    }

    // 3、从栈中取数0和1
    let binaryString = ''
    while (!stack.isEmpty()) {
      binaryString += stack.pop()
    }
    return binaryString
  }

  // 测试十进制转二级制
  console.log(dec2bin(100))

3、队列

队列特性:

  • 1、它是一种受限制的线性表,先进先出
  • 2、受限之处在于它只允许在表前端进行删除
  • 3、而在表后端进行插入操作

image.png

队列的常见操作

  • 1、enqueue():向队列尾部添加一个或多个新项
  • 2、dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
  • 3、front():返回队列中第一个元素——最先被添加,也将是最先被移除的元素,队列不做任何变动(不移除元素,会返回元素信息——与stack类额peek方法非常类似)
  • 4、isEmpty():如果队列中不包含任何元素,返回true,否则返回false
  • 5、size():返回队列中包含元素的个数,与数组的length相似
  • 6、toString():将队列中的内容转成字符串形式

基于数组进行封装

function Queue(){
    //属性
    this.items =[]
    //方法
    // 1、将元素加入到队列中
    Queue.prototype.enqueue = function(element){
      this.items.push(element)
    }
    // 2、删除队列中的前端元素
    Queue.prototype.dequeue = function(){
      return this.items.shift()
    }
    // 3、查看队列中前端元素
    Queue.prototype.front = function(){
      return this.items[0]
    }
    // 4、查看队列是否为空
    Queue.prototype.isEmpty = function(){
        return this.items.length == 0
    }
    // 5、查看队列中元素个数
    Queue.prototype.size = function(){
        return this.items.length
    }
    // 6、toString队列
    Queue.prototype.toString = function(){
      let result = ''
      for(let i=0; i<this.items.length; i++){
        result += this.items[i] + ' '
      }
      return result
    }
}

面试题算法示例

规则:几个朋友一起玩一个游戏,围成一圈,开始数数,数到某一个数字的人自动淘汰,最后剩下的那个人获胜,请问最后获胜的人是原来在哪一个位置上的人

function passGame(nameList, num){
	// 1、创建一个队列结构
	let queue = new Queue()

	//2、将所有人一次加入队列
	for(let i=0;i<nameList.length;i++){
		queue.enqueue(nameList[i])
	}

	// 3、开始数数,
	while (queue.size() > 1) {
		// 不是num的时候,重新加入到队列末尾
		// 如果是num这个数字时,将其从队列中删除
		// 3.1 num之前的人重新放入到队列末尾
		for(let i=0;i<num-1;i++){
			queue.enqueue(queue.dequeue())
		}
		// 3.2 对应num的人,直接冲队列删除掉
		queue.dequeue()
	}

	// 4、剩下的那个人
	let endName = queue.front()

	return {name:endName,index:nameList.indexOf(endName)}
}
//测试击鼓出传花
let nameList = ['张三','李四','王五','小明','小红']
console.log(passGame(nameList,3))

优先级队列

特点

  • 1、优先级队列,在插入一个元素的时候会考虑该数据的优先级
  • 2、和其他数据优先级进行比较
  • 3、比较完成之后,可以得出该元素在队列中的正确位置 主要考虑的问题:
  • 1、每个元素不再是一个数据,而且包含数据的优先级
  • 2、在添加方式中,根据优先级放入正确的位置

生活中优先级队列应用

  • 1、登机的顺序:头等舱,商务舱优先于经济舱登记,老人,孕妇优先登机
  • 2、医院急诊候诊:医生优先处理病情比较严重的病人。

优先级队列封装

function PriorityQueue(){
	//在PriorityQueue重新创建一个类,可以理解成内部类
	function QueueElement(element,priority){
		this.element = element;
		this.priority = priority
	}
	// 封装属性
	this.items = []

	// 插入方法
	PriorityQueue.prototype.enqueue = function(element,priority){
		// 1、创建QueueElement对象
		let queueElement = new QueueElement(element,priority)

		//2、判断队列是否为空
		if(this.items.length == 0){
			this.items.push(queueElement)
		}else{
			let addad = false;
			for(let i=0;i<this.items.length;i++){
				if(queueElement.priority < this.items[i].priority){
					this.items.splice(i,0,queueElement)
					addad = true;
					break
				}
			}
			if(!addad){
				this.items.push(queueElement)
			}
		}
	}

	//其他和普通队列一样
}