如下代码所有原创手写。node
非递归实现:数组
class Node {
constructor(value, next) {
this.value = value;
this.next = next;
}
}
class LinkedList{
constructor() {
this.dummyHead = new Node(null, null);
this.size = 0;
}
//在指定索引处插入一个Node类型的节点
add(index, newNode) {
if(index > this.size || index < 0)
throw new Error('索引非法');
let pre = this.dummyHead;
for(let i = 0; i < index; i++) {
pre = pre.next;
}
newNode.next = pre.next;
pre.next = newNode;
this.size++;
}
//在链表头增长节点
addFirst(newNode) {
this.add(0, newNode);
}
//在链表尾增长节点
addLast(newNode) {
this.add(size, newNode);
}
//删除一个索引为index的节点
remove(index) {
if(index >= this.size || index < 0)
throw new Error('索引非法');
let pre = this.dummyHead;
for (let i = 0; i < index; i++) {
pre = pre.next;
}
let delNode = pre.next;
pre.next = delNode.next;
delNode.next = null;
this.size--;
}
removeFirst() {
this.remove(0);
}
removeLast() {
this.remove(this.size - 1);
}
//删除值为value的节点
removeElement(value) {
let pre = this.dummyHead;
//找到待删除节点的前一个节点
while (pre.next != null) {
if (pre.next.value == value)
break;
pre = pre.next;
}
if (pre.next != null) {
let cur = pre.next;
pre.next = cur.next;
cur.next = null;
this.size--;
return cur;
}
return null;
}
contains(value) {
let cur = this.dummyHead.next;
while(cur != null) {
if(cur.value === value) {
return true;
}
cur = cur.next;
}
return false;
}
getSize() {
return this.size;
}
isEmpty() {
return this.size == 0;
}
toString() {
let cur = this.dummyHead.next;
let str = "";
while (cur != null){
str += cur.value + "->";
cur = cur.next;
}
str += "null";
return str;
}
}
function test() {
let n1 = new Node(1, null);
let n2 = new Node(4, null);
let n3 = new Node(3, null);
let n4 = new Node(2, null);
let list = new LinkedList();
list.addFirst(n1);
list.addFirst(n2);
list.addFirst(n3);
list.addFirst(n4);
console.log("链表初始化:", list.toString());
list.remove(3);
console.log("删除第3个元素后为:", list.toString());
list.removeElement(3);
console.log("删除值为3的元素后为:", list.toString());
console.log("链表元素个数:", list.getSize());
}
test();
复制代码
测试结果:函数
下面是递归方法的实现,会有一些绕,可是并非太难理解,但愿你们耐心看下来:post
class Node {
constructor(value, next) {
this.value = value;
this.next = next;
}
}
class LinkedList{
constructor() {
this.dummyHead = new Node(null, null);
this.size = 0;
}
//在指定索引处插入一个Node类型的节点,递归写法
add(index, newNode) {
if(index > this.size || index < 0)
throw new Error('索引非法');
let pre = this.dummyHead;
pre.next = this._add(index, pre.next, newNode, 0);
this.size++;
}
_add(index, cur, newNode, depth) {
//递归深度达到索引值时,即当前的cur指向第index个元素时,咱们作一些处理
//让函数返回插入的节点,即让第index-1个元素的next指向了要插入的节点,如下递归写法均为同理
if (index == depth) {
newNode.next = cur;
return newNode;
}
cur.next = this._add(index, cur.next, newNode, depth + 1);
return cur;
}
//在链表头增长节点
addFirst(newNode) {
this.add(0, newNode);
}
//在链表尾增长节点
addLast(newNode) {
this.add(size, newNode);
}
//删除一个索引为index的节点,递归写法
remove(index) {
if(index >= this.size || index < 0)
throw new Error('索引非法');
let pre = this.dummyHead;
pre.next = this._remove(index, pre.next, 0);
this.size--;
}
_remove(index, cur, depth) {
if (index === depth) {
let nextNode = cur.next;
cur.next = null;
return nextNode;
}
cur.next = this._remove(index, cur.next, depth + 1);
return cur;
}
removeFirst() {
this.remove(0);
}
removeLast() {
this.remove(this.size - 1);
}
//删除值为value的节点, 递归写法
removeElement(value) {
let pre = this.dummyHead;
pre.next = this._removeElement(pre.next, value);
}
_removeElement(cur, value) {
if(cur.value === value) {
let nextNode = cur.next;
cur.next = null;
this.size--;
return nextNode;
}
cur.next = this._removeElement(cur.next, value);
return cur;
}
contains(value) {
let cur = this.dummyHead.next;
while(cur != null) {
if(cur.value === value) {
return true;
}
cur = cur.next;
}
return false;
}
getSize() {
return this.size;
}
isEmpty() {
return this.size == 0;
}
toString() {
let cur = this.dummyHead.next;
let str = "";
while (cur != null){
str += cur.value + "->";
cur = cur.next;
}
str += "null";
return str;
}
}
function test() {
let n1 = new Node(1, null);
let n2 = new Node(4, null);
let n3 = new Node(3, null);
let n4 = new Node(2, null);
let list = new LinkedList();
list.addFirst(n1);
list.addFirst(n2);
list.addFirst(n3);
list.addFirst(n4);
console.log("链表初始化:", list.toString());
list.remove(3);
console.log("删除第3个元素后为:", list.toString());
list.removeElement(3);
console.log("删除值为3的元素后为:", list.toString());
console.log("链表元素个数:", list.getSize());
}
test();
复制代码
测试结果:测试
能够看到,递归方法的结果和非递归是彻底同样的,说明递归的实现没有问题。ui
在二分搜索树中,任何的节点的值大于左孩子节点,并且小于右孩子节点。this
如今来实现其中全部的方法,其中三种顺序的遍历都有递归和非递归的方式:spa
class Node{
constructor(value, left, right) {
this.value = value;
this.left = left || null;
this.right = right || null;
this.isVisited = false;
}
}
class BST{
constructor() {
this.root = null;
this.size = 0;
}
getSize() {
return this.size;
}
isEmpty() {
return this.size === 0;
}
add(value) {
this.root = this._add(this.root, value);
}
_add(node, value) {
if(node == null) {
let newNode = new Node(value);
this.size++;
return newNode;
}
if(value < node.value)
node.left = this._add(node.left, value);
if(value > node.value)
node.right = this._add(node.right, value);
//等于的状况不作处理
return node;
}
contains(value) {
return this._contains(this.root, value);
}
_contains(node, value) {
if(node == null)
return false;
if(value < node.value)
return this._contains(node.left, value);
else if(value > node.value)
return this._contains(node.right, value);
else if(value === node.value)
return true;
}
//先序遍历 递归方式
preOrder() {
this._preOrder(this.root);
}
_preOrder(node) {
if(node == null)
return;
console.log(node.value);
this._preOrder(node.left);
this._preOrder(node.right);
}
//先序遍历 非递归方式
preOrderNR() {
//这里须要用到栈,js数组的push和pop就能知足
let stack = [];
let p = this.root;
while(!stack.length || p != null) {
while(p != null) {
stack.push(p);
console.log(p.value);
p = p.left;
}
let q = stack.pop();
p = q.right;
}
}
//中序遍历 递归方式
inOrder() {
this._inOrder(this.root);
}
_inOrder(node) {
if(node == null)
return;
this._inOrder(node.left);
console.log(node.value);
this._inOrder(node.right);
}
//中序遍历 非递归方式
inOrderNR() {
//这里一样须要用到栈,js数组的push和pop就能知足
let stack = [];
let p = this.root;
while(stack.length || p != null) {
while(p != null) {
stack.push(p);
p = p.left;
}
let q = stack.pop();
console.log(q.value);
p = q.right;
}
}
//后序遍历 递归方式
postOrder() {
this._postOrder(this.root);
}
_postOrder(node) {
if(node == null)
return;
this._inOrder(node.left);
this._inOrder(node.right);
console.log(node.value);
}
//后序遍历 非递归方式
postOrderNR() {
//这里一样也须要用到栈,js数组的push和pop就能知足
let stack = [];
let p = this.root;
while(stack.length || p != null) {
while(p != null) {
stack.push(p);
p = p.left;
}
//拿到栈顶元素
let peek = stack[stack.length - 1];
if(peek.right != null && !peek.right.isVisited)
p = peek.right;
else{
let q = stack.pop();
console.log(q.value);
q.isVisited = true;
}
}
}
//层序遍历
levelOrder() {
//须要用到队列,用js数组的shift和push就能知足
let queue = [];
queue.push(this.root);
while(queue.length) {
let cur = queue.shift();
console.log(cur.value);
if(cur.left != null)
queue.push(cur.left);
if(cur.right != null)
queue.push(cur.right);
}
}
//找到BST节点中的最小值
minimum() {
return this._minimum(this.root).value;
}
_minimum(node) {
if(node.left == null) {
return node;
}
return this._minimum(node.left);
}
maximum() {
return this._maximum(this.root).value;
}
_maximum(node) {
if(node.right == null) {
return node;
}
return this._maximum(node.right);
}
removeMin() {
let ret = this.minimum(this.root);
this.root = this._removeMin(this.root);
return ret;
}
_removeMin(node) {
if(node.left == null) {
let right = node.right;
node.right = null;
this.size--;
return right;
}
node.left = this._removeMin(node.left);
return node;
}
removeMax() {
let ret = this.maximum(this.root);
this.root = this._removeMax(this.root);
return ret;
}
_removeMax(node) {
if(node.right == null) {
let left = node.left;
node.left = null;
this.size--;
return left;
}
node.right = this._removeMax(node.right);
return node;
}
remove(value) {
this.root = this._remove(this.root, value);
return value;
}
_remove(node, value) {
if(value <node.value) {
node.left = this._remove(node.left);
return node;
} else if(value > node.value){
node.right = this._remove(node.right);
return node;
} else {
//要开始删除了
if(node.left == null) {
let right = node.right;
node.right = null;
this.size--;
return right;
}
if(node.right == null) {
let left = node.left;
node.left = null;
this.size--;
return left;
}
//最小的后继节点
let successor = this._minimum(node.right);
successor.right = this._removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
this.size--;
return successor;
}
}
toString() {
this._generateBST(this.root, 0);
}
//先序遍历打印树的结构
_generateBST(node, depth){
if(node == null){
console.log(this._generateDepthString(depth), "null");
return;
}
console.log(this._generateDepthString(depth), node.value);
this._generateBST(node.left, depth+1);
this._generateBST(node.right, depth+1);
}
_generateDepthString(depth) {
let str = "";
for(let i = 0; i < depth; i++) {
str += "--"
}
return str;
}
}
function test() {
let bst = new BST();
bst.add(2);
bst.add(6);
bst.add(5);
bst.add(3);
bst.add(7);
// console.log("先序遍历");
// bst.preOrder();
// bst.preOrderNR();
// console.log("中序遍历");
// bst.inOrder();
// bst.inOrderNR();
// console.log("后序遍历");
// bst.postOrder();
// bst.postOrderNR();
// console.log("层序遍历");
// bst.levelOrder();
// console.log("最大值", bst.maximum());
// console.log("最小值", bst.minimum());
// console.log(bst.contains(2));//true
// console.log(bst.removeMin());
// console.log(bst.removeMax());
console.log(bst.remove(6));
bst.toString();
}
test();
复制代码
堆的结构实现以下:debug
class MaxHeap{
constructor(arr = [], compare = null) {
this.data = arr;
this.size = arr.length;
this.compare = compare || function(a, b){return a - b > 0};
}
getSize() {
return this.size;
}
isEmpty() {
return this.size === 0;
}
_swap(i, j) {
[this.data[i], this.data[j]] = [this.data[j], this.data[i]];
}
_parent(index) {
return Math.floor((index - 1) / 2);
}
_leftChild(index) {
return 2 * index + 1;
}
_rightChild(index) {
return 2 * index + 2;
}
_siftUp(k) {
while(k > 0 && this.data[k] > this.data[this._parent(k)]){
this._swap(k, this._parent(k));
k = this._parent(k);
}
}
_siftDown(k) {
while(this._leftChild(k) < this.size) {
let j = this._leftChild(k);
debugger;
if(this._rightChild(k) < this.size &&
this.compare(this.data[this._rightChild(k)], this.data[j])){
j++;
}
if(this.data[k] >= this.data[j])
return;
this._swap(k, j);
k = j;
}
}
//增长元素
add(value) {
this.data.push(value);
this.size++;
this._siftUp(this.getSize() - 1);
}
findMax() {
if(this.getSize() === 0)
return;
return this.data[0];
}
extractMax() {
let ret = this.findMax();
this._swap(0, this.getSize() - 1);
this.data.pop();
this.size--;
this._siftDown(0);
return ret;
}
toString() {
console.log(this.data);
}
}
module.exports = MaxHeap;
复制代码
所谓优先队列,就是每次出队的时候,老是出队列中权值最高的元素。code
如今能够用堆来轻易地实现:
const MaxHeap = require('./maxHeap');
class PriorityQueue {
constructor() {
this.maxHeap = new MaxHeap();
}
getSize() {
return this.maxHeap.getSize();
}
isEmpty() {
return this.maxHeap.isEmpty();
}
getFront() {
return this.maxHeap.findMax();
}
enqueue(e) {
return this.maxHeap.add(e);
}
dequeue() {
return this.maxHeap.extractMax();
}
}
let pq = new PriorityQueue();
pq.enqueue(1);
pq.enqueue(3);
pq.enqueue(6);
pq.enqueue(2);
pq.enqueue(62);
console.log(pq.dequeue());
复制代码