学习常见数据结构(一)

时间复杂度

通常使用最差的时间复杂度来衡量一个算法的好坏。

常数时间 O(1) 代表这个操作和数据量没关系,是一个固定时间的操作,比如说四则运算。

对于一个算法来说,可能会计算出操作次数为 aN + 1,N 代表数据量。那么该算法的时间复杂度就是 O(N)。因为我们在计算时间复杂度的时候,数据量通常是非常大的,这时候低阶项和常数项可以忽略不计。

当然可能会出现两个算法都是 O(N) 的时间复杂度,那么对比两个算法的好坏就要通过对比低阶项和常数项了。

栈是一个线性结构,在计算机中是一个相当常见的数据结构。
栈的特点是只能在某一端添加或删除数据,遵循先进后出的原则
每种数据结构都可以用很多种方式来实现,其实可以把栈看成是数组的一个子集,所以这里使用数组来实现:

class Stack {
  constructor() {
    this.stack = []
 }
push(item)  {
   this.stack.push(item)
}
pop() {
  this.stack.pop()
}
peek() {
  return this.stack[this.getCount() - 1]
}
getCount() {
return this.stack.length
}
isEmpty() {
   return this.getCount() === 0
}
}

练习题:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true

var isValid = function(s) {
		let map = {
			"(" : -1,
			")" : 1,
			'[': -2,
			']': 2,
			'{': -3,
			'}': 3
		}
		let stack = [];
		for (let i=0; i<s.length;i++){
			if (map[s[i]]<0){
				stack.push(s[i])
			}else {
				let last = stack.pop()
				if (map[last] + map[s[i]] !==0 ) return false;
			}
		}
		if (stack.length > 0 )return false;
		return true;
	}

队列

队列是一个线性结构,特点是在某一端添加数据,在另一端删除数据,遵循先进先出的原则。
有俩种实现队列的方式,分别是单链队列和循环队列。

单链队列

class Queue {
	constructor() {
		this.queue = []
	}
	enQueue(item) {
		this.queue.push(item)
	}
	deQueue() {
		return this.queue.shift()
	}
	getHeader() {
		return this.queue[0]
	}
	getLength() {
		return this.queue.length
	}
	isEmpty() {
		return this.getLength() === 0
	}
}

因为单链队列在出队操作的时候需要 O(n) 的时间复杂度,所以引入了循环队列。循环队列的出队操作平均是 O(1) 的时间复杂度。

循环队列

class SqQueue {
	constructor(length) {
		this.queue = new Array(length + 1)
		// 队头
		this.first = 0
		// 队尾
		this.last = 0
		// 当前队列大小
		this.size = 0
	}
	enQueue(item) {
		// 判断队尾 + 1 是否为队头
		// 如果是就代表需要扩容数组
		// % this.queue.length 是为了防止数组越界
		if (this.first === (this.last + 1) % this.queue.length) {
		  this.resize(this.getLength() * 2 + 1)
		}
		this.queue[this.last] = item
		this.size++
		this.last = (this.last + 1) % this.queue.length
	}
	deQueue() {
		if (this.isEmpty()) {
		throw Error('Queue is empty')
	}
	let r = this.queue[this.first]
	this.queue[this.first] = null
	this.first = (this.first + 1) % this.queue.length
	this.size--
	// 判断当前队列大小是否过小
	// 为了保证不浪费空间,在队列空间等于总长度四分之一时
	// 且不为 2 时缩小总长度为当前的一半
	if (this.size === this.getLength() / 4 && this.getLength() / 2 !== 0) {
		this.resize(this.getLength() / 2)
	}
	return r
	}
	getHeader() {
		if (this.isEmpty()) {
			throw Error('Queue is empty')
		}
		return this.queue[this.first]
	}
	getLength() {
		return this.queue.length - 1
	}
	isEmpty() {
		return this.first === this.last
	}
	resize(length) {
		let q = new Array(length)
		for (let i = 0; i < length; i++) {
			q[i] = this.queue[(i + this.first) % this.queue.length]
		}
		this.queue = q
		this.first = 0
		this.last = this.size
	}
}

发布了25 篇原创文章 · 获赞 7 · 访问量 9214

猜你喜欢

转载自blog.csdn.net/Beth__hui/article/details/101460457