毕业一年半,一事无成,遥想当年还未毕业整体憧憬着毕业以后大展宏图,但是毕业后却不如所愿,如今工作一年多技术不但涨进不多,反而忘了学校的知识。临近新年,我思索良久,我这一生都一直得过且过,小学考试成绩不被父母老师骂就行,中学成绩能考上大学就行,大学不挂科就行,如今工作了有工作饿不死就行。但...如今我不想这样,我不想得过且过了,因此我决定学习。其实毕业后我一直很迷茫,因为工作比较简单,都是写写页面,所以我一直找不到学习的方向,想学的东西很多,但是不知道从何学起,如今我虽然也还迷茫,但我不会停滞不前了,在这个全互联网都说"前端已死"的大潮中,我就从数据结构与算法开始学习与分享吧。
什么时数据结构与算法
什么是数据结构
民间定义:
"数据结构是数据对象,以及存在于该对象的实例和 组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。" --- 《数据结构、算法与应用》"
数据结构是ADT( 抽象数据类型 Abstract Data Type)的物理实现。"---《数据结构与算法分析》
数据结构( data structure )是计算机中存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法。---中文维基百科
从个人的角度来数据结构:
口数据结构就是在计算机中存储和组织数据的方式
什么是算法
算法的定义:
一个有限指令集,每条指令的描述不依赖于语言
接受一些输入( 有些情况下不需要输入)
产生输出
一定在有限步骤之后终止
算法通俗的理解:
解决问题的方法、步骤
栈结构(Stack)
栈 是比较常见的受限的线性结构 ,栈的特点为先进后出,后进先出。
栈常见的操作:
- push(element):添加一个新元素到栈顶位置;
- pop():移除栈顶的元素,同时返回被移除的元素;
- peek():返回栈顶的元素,不对栈做任何修改(该方法不会移除栈顶的元素,仅仅返回它);
- isEmpty():如果栈里没有任何元素就返回true,否则返回false;
- size():返回栈里的元素个数。这个方法和数组的length属性类似;
- toString():将栈结构的内容以字符串的形式返回。
基于数组实现栈以及通过栈实现十进制转二进制
typescript
// 基于数组实现栈
class Stack{
item = []
constructor(){
this.item = []
}
//添加一个新元素到栈顶位置
push(element: any){
this.item.push(element)
}
//移除栈顶的元素,同时返回被移除的元素;
pop(){
return this.item.pop()
}
//查看一下栈顶元素
peek(){
return this.item[this.item.length - 1]
}
//isEmpty():判断栈是否为空
isEmpty(){
return this.item.length === 0
}
//获取栈中元素的个数
size(){
return this.item.length
}
//以字符串形式输出栈内数据
toString(){
let str = ''
for(let i of this.item){
str += i + ''
}
return str
}
}
let stack = new Stack()
stack.push(23)
stack.push(140)
stack.push(109)
stack.push(77)
console.log(stack)
console.log(stack.pop())
console.log(stack.pop())
console.log(stack.peek())
console.log(stack.isEmpty())
console.log(stack.size())
console.log(stack.toString())
// 利用栈将十进制转二进制
function dec2bin(num: number){
const stack2 = new Stack()
while(num > 0){
stack2.push(num % 2)
num = Math.floor(num / 2)
}
// return stack2
let str = ''
while(stack2.item.length !== 0){
str += stack2.pop() + ''
}
return str
}
console.log(dec2bin(100),'---')
队列结构(Queue)
队列和栈一样是一种受限的线性表,不同的是队列的特点为先进先出 (FIFO:first in first out)。
队列的常见操作:
- enqueue(element):向队列尾部添加一个(或多个)新的项;
- dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素;
- front():返回队列中的第一个元素------最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息与Stack类的peek方法非常类似);
- isEmpty():如果队列中不包含任何元素,返回true,否则返回false;
- size():返回队列包含的元素个数,与数组的length属性类似;
- toString():将队列中的内容,转成字符串形式;
队列的封装
typescript
class Queue{
item = []
constructor(){
this.item = []
}
//向队列尾部添加新的项;
enqueue(element:any){
this.item.push(element)
}
//移除队列的第一(即排在队列最前面的)项,并返回被移除的元素;
dequeue(){
return this.item.shift()
}
// 返回队列中的第一个元素------最先被添加,也将是最先被移除的元素。
front(){
return this.item[0]
}
// 如果队列中不包含任何元素,返回true,否则返回false;
isEmpty(){
return this.item.length === 0
}
// 返回队列包含的元素个数,与数组的length属性类似;
size(){
return this.item.length
}
// 将队列中的内容,转成字符串形式;
toString(){
let str = ''
for(let i of this.item){
str += i + ''
}
return str
}
}
// 创建队列
let queue = new Queue()
// 将元素加入到队列中
queue.enqueue('aa')
queue.enqueue('bb')
queue.enqueue('cc')
queue.enqueue('dd')
console.log(queue);
// 从队列中删除元素
queue.dequeue()
console.log(queue);
//front
console.log(queue.front());
// 验证其他方法
console.log(queue.isEmpty());
console.log(queue.size());
console.log(queue.toString());
队列常见的算法
scss
//击鼓传花
function payGame(numList:any, num:number){
let queue2 = new Queue()
for(let i of numList){
queue.enqueue(i)
}
while(queue.size() > 1){
// 不是num的时候,重新加入队列末尾
// 是num的时候,将其从队列中删除
// num数字之前的人重新放入队列的末尾(把队列前面删除的加到队列最后)
for(let i = 0; i < num - 1; i++){
queue.enqueue(queue.dequeue())
}
queue.dequeue()
}
return queue.front()
}
const names = ['zhangsan', 'lisi', 'wangwu', 'zhaoliu', 'lihua']
console.log(payGame(names, 3),'====');
优先级队列
什么是优先级队列
队列是一种先进先出(First in First out,FIFO)的数据类型。每次元素的入队都只能添加到队列尾部,出队时从队列头部开始出。
优先级队列(priority_queue)其实,不满足先进先出的条件,更像是数据类型中的"堆"。优先级队列每次出队的元素是队列中优先级最高的那个元素,而不是队首的元素。这个优先级可以通过元素的大小等进行定义。比如定义元素越大优先级越高,那么每次出队,都是将当前队列中最大的那个元素出队。
kotlin
//优先级队列代码封装
class QueueElement{
item = []
constructor(){
this.item = []
}
//向队列尾部添加新的项;
enqueue(element,priority){
if(this.item.length == 0){
this.item.push({element:element,priority:priority})
}else{
// 定义一个变量记录是否成功添加了新元素
let added = false
let index = 0
for(const i of this.item){
// 让新插入的元素与原有元素进行优先级比较(priority越小,优先级越大)
if(priority < i.priority){
this.item.splice(index, 0, {element:element,priority:priority})
added = true
// 新元素已经找到插入位置了可以使用break停止循环
break
}
index = index + 1
}
// 新元素没有成功插入,就把它放在队列的最前面
if(!added){
this.item.push({element:element,priority:priority})
}
}
}
//移除队列的第一(即排在队列最前面的)项,并返回被移除的元素;
dequeue(){
return this.item.shift()
}
// 返回队列中的第一个元素------最先被添加,也将是最先被移除的元素。
front(){
return this.item[0]
}
// 如果队列中不包含任何元素,返回true,否则返回false;
isEmpty(){
return this.item.length === 0
}
// 返回队列包含的元素个数,与数组的length属性类似;
size(){
return this.item.length
}
// 将队列中的内容,转成字符串形式;
toString(){
let str = ''
for(let i of this.item){
str += i + ''
}
return str
}
}
// 创建队列
const queueElement = new QueueElement()
// 将元素加入到队列中
queueElement.enqueue('aa',11)
queueElement.enqueue('bb',22)
queueElement.enqueue('rr',55)
queueElement.enqueue('yy',77)
queueElement.enqueue('cc',33)
queueElement.enqueue('dd',44)
console.log(queueElement,'=========');