栈
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表 由于栈具有后入先出的特点,所以任何不在栈顶的元素都无法访问。为了得到栈底的元素,必须先拿掉上面的元素。
对栈的两种主要操作是将一个元素压入栈和将一个元素弹出栈。入栈使用 push()方法,出栈使用 pop()方法,下面用代码实现栈这种数据结构
实现栈类
- dataStore代表数据集
top代表栈顶坐标
class Stack{ dataStore=[] top=0 constructor(){ } }
push():进栈
push(element){
this.dataStore[this.top++] = element
}
pop():出栈
pop(){
let element = this.dataStore[--this.top]
this.dataStore.length = this.top
return element
}
peek():返回栈顶
peek(){
return this.dataStore[this.top-1]
}
length():数据的数量
length() {
return this.top;
}
clear():清空栈
clear() {
this.top = 0;
this.dataStore.length=0
}
完整代码
class Stack {
dataStore = []
top = 0
constructor() {
}
push(element) {
this.dataStore[this.top++] = element
}
pop() {
let element = this.dataStore[--this.top]
this.dataStore.length = this.top
return element
}
peek() {
return this.dataStore[this.top - 1]
}
length() {
return this.top;
}
clear() {
this.top = 0;
this.dataStore.length = 0
}
}
队列
队列是一种列表,一种只能在队尾插入元素,在队首删除元素的列表。队列用于存储按顺序排列的数据,先进先出队列的两种主要操作是:向队列中插入新元素和删除队列中的元素。插入操作也叫做入队,删除操作也叫做出队。入队操作在队尾插入新元素,出队操作删除队头的元素。
下面用代码实现队列
实现 Queue 类
dataStore代表数据集
class Queue {
dataStore = []
constructor() {
}
}
enqueue() 方法向队尾添加一个元素
enqueue(element) {
this.dataStore.push(element)
}
dequeue() 方法删除队首的元素
dequeue() {
return this.dataStore.shift()
}
可以使用如下方法读取队首和队尾的元素
front() {
return this.dataStore[0]
}
back() {
return this.dataStore[this.dataStore.length - 1]
}
toString() 方法显示队列内的所有元素
toString() {
return String(this.dataStore)
}
判断队列是否为空
empty() {
return this.dataStore.length == 0
}
完成代码
class Queue {
dataStore = []
constructor() {
}
enqueue(element) {
this.dataStore.push(element)
}
dequeue() {
return this.dataStore.shift()
}
front() {
return this.dataStore[0]
}
back() {
return this.dataStore[this.dataStore.length - 1]
}
toString() {
return String(this.dataStore)
}
empty() {
return this.dataStore.length == 0
}
}
链表
链表是由一组节点组成的集合。每个节点都使用一个对象的引用指向它的后继。指向另一个节点的引用叫做链。标识出链表的起始节点却有点麻烦,因此在链表最前面有一个特殊节点,叫做头节点
设计的链表包含两个类。Node类用来表示节点,LinkedList类提供了插入节点、删除节点、显示列表元素的方法,以及其他一些辅助方法。
Node类
节点包含数据和指针,如下图所示
- element代表元素
next为指针
class Node { constructor(element){ this.element=element this.next=null } }
LinkedList类
链表创建默认给个头结点
class LinkedList {
constructor(){
this.head = new Node('head')
}
}
find()查找一个节点
//从头遍历开始查找
find(item){
let node = this.head
while(node&&node.element != item){
node = node.next
}
return node
}
findPrevious()查找目标前一个节点
findPrevious(item){
let node = this.head
while(node.next&&node.next.element != item){
node = node.next
}
return node.next?node:null
}
insert()插入新节点
插入节点是将新元素节点的指针指向目标元素指针指向的节点,再讲目标节点的指针指向新节点
insert(element,item){
let node = this.find(item)
if(node){
let newNode = new Node(element)
newNode.next = node.next
node.next = newNode
}
}
remove()删除一个节点
删除节点是将目标节点的上一个节点指向目标节点的下一个节点
remove(item){
let node = this.findPrevious(item)
if(node){
node.next = node.next.next
}
}
display()打印链表
display(){
let node = this.head
while(node){
console.log(node.element)
node = node.next
}
}
完整代码
class Node {
constructor(element) {
this.element = element
this.next = null
}
}
class LinkedList {
constructor() {
this.head = new Node('head')
}
find(item) {
let node = this.head
while (node && node.element != item) {
node = node.next
}
return node
}
findPrevious(item) {
let node = this.head
while (node.next && node.next.element != item) {
node = node.next
}
return node.next ? node : null
}
insert(element, item) {
let node = this.find(item)
if (node) {
let newNode = new Node(element)
newNode.next = node.next
node.next = newNode
}
}
remove(item) {
let node = this.findPrevious(item)
if (node) {
node.next = node.next.next
}
}
display() {
let node = this.head
while (node) {
console.log(node.element)
node = node.next
}
}
}
双向链表
尽管从链表的头节点遍历到尾节点很简单,但反过来,从后向前遍历则没那么简单。通过给Node对象增加一个属性,该属性存储指向前驱节点的链接,这样就容易多了。此时向链表插入一个节点需要更多的工作,我们需要指出该节点正确的前驱和后继。但是在从链表中删除节点时,效率提高了,不需要再查找待删除节点的前驱节点了
Node类
双向链表的节点比单向链表的节点多了一个前驱指针previous
class Node {
constructor(element){
this.element=element
this.next=null
this.previous = null
}
}
实现双向链表
class DoubleLink{
constructor(){
this.head = new Node('head')
}
}
查找一个元素
find(item){
let node = this.head
while(node&&node.element != item){
node = node.next
}
return node
}
查找前一个元素
findPrevious(item){
let node = this.head
while(node.next&&node.next.element != item){
node = node.next
}
return node.next?node:null
}
查找最后一个元素
findLast(){
let node = this.head
while(node.next){
node = node.next
}
return node
}
插入一个元素
插入节点,除了和单向链表一样的操作外,后一个节点的前驱指针得指向要插入的节点,插入的节点的前驱指针需要指向前一个节点
insert(element,item){
let node = this.find(item)
if(node){
let newNode = new Node(element)
newNode.previous = node
if( node.next){
node.next.previous = newNode
}
newNode.next = node.next
node.next = newNode
}
}
删除一个元素
remove(item){
let node = this.findPrevious(item)
if(node){
if(node.next.next){
node.next.next.previous = node
}
node.next = node.next.next
}
}
打印元素
display(){
let node = this.head
while(node){
console.log(node.element)
node = node.next
}
}
逆向打印链表
dispReverse(){
let node = this.findLast()
while(node){
console.log(node.element)
node = node.previous
}
}
完整代码
class Node {
constructor(element) {
this.element = element
this.next = null
this.previous = null
}
}
class DoubleLink {
constructor() {
this.head = new Node('head')
}
find(item) {
let node = this.head
while (node && node.element != item) {
node = node.next
}
return node
}
findPrevious(item) {
let node = this.head
while (node.next && node.next.element != item) {
node = node.next
}
return node.next ? node : null
}
findLast() {
let node = this.head
while (node.next) {
node = node.next
}
return node
}
insert(element, item) {
let node = this.find(item)
if (node) {
let newNode = new Node(element)
newNode.previous = node
if (node.next) {
node.next.previous = newNode
}
newNode.next = node.next
node.next = newNode
}
}
remove(item) {
let node = this.findPrevious(item)
if (node) {
if (node.next.next) {
node.next.next.previous = node
}
node.next = node.next.next
}
}
display() {
let node = this.head
while (node) {
console.log(node.element)
node = node.next
}
}
dispReverse() {
let node = this.findLast()
while (node) {
console.log(node.element)
node = node.previous
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。