一、单向链表
js实现单向链表
class Node {
constructor(element, next) {
this.element = element;
this.next = next;
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0; // 链表长度
}
add(index, element) {
// 如果只传了一个参数,统一成两个的形式
if (arguments.length === 1) {
element = index;
index = this.size;
}
// 越界判断
if (index < 0 || index > this.size) throw new Error('越界');
// 第一个节点
if (index === 0) {
let head = this.head;
this.head = new Node(element, head);
// 不是第一个节点,修改next指针
} else {
let prevNode = this._node(index - 1); // 找前一个节点,索引是size-1
prevNode.next = new Node(element, prevNode.next);
}
this.size++;
}
remove(index) {
let removeNode;
// 只有一个的情况,删除的是头
if (index === 0) {
removeNode = this.head;
if (removeNode) {
this.head = this.head.next;
this.size--;
}
// 有多个,则把上一个的指针指向以上一个为基础的,下一个的下一个
} else {
let prevNode = this._node(index - 1);
removeNode = prevNode.next;
prevNode.next = prevNode.next.next;
this.size--;
}
return removeNode;
}
// 查找节点
_node(index) {
let current = this.head;
for (let i = 0; i < index; i++) {
current = current.next;
}
return current;
}
get(index) {
return this._node(index);
}
set(index, element) {
let node = this._node(index);
node.element = element;
return node;
}
clear() {
this.size = 0;
this.head = null;
}
}
let link = new LinkedList();
link.add(1);
link.add(2);
link.add(3);
console.dir(link, {depth: 100});
module.exports = LinkedList;
/*
LinkedList {
head: Node {
element: 1,
next: Node { element: 2, next: Node { element: 3, next: null } }
},
size: 3
}
*/
1.单链表反转
1) 递归实现-两两反转
reverse() {
function r(head) {
// 空链表或者只有一个
if (head == null || head.next == null) return head;
// 从最后面开始反转
let newHead = r(head.next);
// 指针反转
head.next.next = head;
// 老头指针指向null
head.next = null;
// 返回新头
return newHead;
}
this.head = r(this.head);
return this.head;
}
2)循环遍历-新链表
reverseLoop() {
let head = this.head;
if (head == null || head.next == null) return head;
let newHead = null;
while(head !== null) {
let temp = head.next; // 保存2
head.next = newHead; // head.next = null
newHead = head; // newHead = 1 1.next = null
head = temp; // 老的头边成了2
}
this.head = newHead;
return newHead;
}
二叉搜索树
class Node {
constructor(element, parent) {
this.element = element;
this.parent = parent;
this.left = null;
this.right = null;
}
}
class Tree {
constructor() {
this.root = null;
}
add(element) {
if (!this.root) {
return this.root = new Node(element, null);
}
let currentNode = this.root;
let parent;
let compare;
// 遍历找到父节点,左右分开
while(currentNode) {
compare = currentNode.element < element;
parent = currentNode;
if (compare) {
currentNode = currentNode.right;
} else {
currentNode = currentNode.left;
}
}
// 绑定父节点和子节点
let node = new Node(element, parent);
if (compare) {
parent.right = node;
} else {
parent.left = node;
}
}
}
let tree = new Tree();
[10, 8, 19, 6, 15, 22, 20].forEach(item => {
tree.add(item);
})
console.dir(tree, { depth: 100 });
1.二叉树遍历
1)先序遍历
// 先序遍历
preOrderTraversal() {
function traversal(node) {
if (node === null) return;
console.log(node.element);
traversal(node.left);
traversal(node.right);
}
traversal(this.root);
}
// tree.preOrderTraversal();
2)中序遍历
// 中序遍历
inOrderTraversal() {
function traversal(node) {
if (node === null) return;
traversal(node.left);
console.log(node.element);
traversal(node.right);
}
traversal(this.root);
}
// tree.inOrderTraversal();
3)后序遍历
// 后序遍历
postOrderTraversal() {
function traversal(node) {
if (node === null) return;
traversal(node.left);
traversal(node.right);
console.log(node.element);
}
traversal(this.root);
}
// tree.postOrderTraversal();
4) 层序遍历
levelOrderTraversal(cb) {
let stack = [this.root];
let index = 0;
let currentNode;
while (currentNode = stack[index++]) {
cb(currentNode);
if (currentNode.left) {
stack.push(currentNode.left);
}
if (currentNode.right) {
stack.push(currentNode.right);
}
}
}
// tree.levelOrderTraversal((node) => {
// node = node.element + 1;
// })
5) 二叉树蛇形遍历
2.二叉树反转
reverse(cb) {
let stack = [this.root];
let index = 0;
let currentNode;
while (currentNode = stack[index++]) {
cb && cb(currentNode);
// 左节点和右节点反转
let temp = currentNode.left;
currentNode.left = currentNode.right;
currentNode.right = temp;
if (currentNode.left) {
stack.push(currentNode.left);
}
if (currentNode.right) {
stack.push(currentNode.right);
}
}
}
let tree = new Tree();
[10, 8, 19, 6, 15, 22, 20].forEach(item => {
tree.add(item);
})
tree.reverse((node) => {
console.log(node.element); // 10, 19, 8, 22, 15, 6, 20
})