|
3 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
4 | 4 |
|
5 | 5 | - [栈](#%E6%A0%88)
|
6 |
| - - [原理](#%E5%8E%9F%E7%90%86) |
| 6 | + - [概念](#%E6%A6%82%E5%BF%B5) |
7 | 7 | - [实现](#%E5%AE%9E%E7%8E%B0)
|
8 | 8 | - [应用](#%E5%BA%94%E7%94%A8)
|
9 | 9 | - [队列](#%E9%98%9F%E5%88%97)
|
10 |
| - - [原理](#%E5%8E%9F%E7%90%86-1) |
| 10 | + - [概念](#%E6%A6%82%E5%BF%B5-1) |
11 | 11 | - [实现](#%E5%AE%9E%E7%8E%B0-1)
|
12 | 12 | - [单链队列](#%E5%8D%95%E9%93%BE%E9%98%9F%E5%88%97)
|
13 | 13 | - [循环队列](#%E5%BE%AA%E7%8E%AF%E9%98%9F%E5%88%97)
|
14 | 14 | - [链表](#%E9%93%BE%E8%A1%A8)
|
15 |
| - - [原理](#%E5%8E%9F%E7%90%86-2) |
| 15 | + - [概念](#%E6%A6%82%E5%BF%B5-2) |
16 | 16 | - [实现](#%E5%AE%9E%E7%8E%B0-2)
|
17 | 17 | - [树](#%E6%A0%91)
|
18 | 18 | - [二叉树](#%E4%BA%8C%E5%8F%89%E6%A0%91)
|
19 | 19 | - [二分搜索树](#%E4%BA%8C%E5%88%86%E6%90%9C%E7%B4%A2%E6%A0%91)
|
20 | 20 | - [实现](#%E5%AE%9E%E7%8E%B0-3)
|
| 21 | +- [Trie](#trie) |
| 22 | + - [概念](#%E6%A6%82%E5%BF%B5-3) |
| 23 | + - [实现](#%E5%AE%9E%E7%8E%B0-4) |
| 24 | +- [并查集](#%E5%B9%B6%E6%9F%A5%E9%9B%86) |
| 25 | + - [概念](#%E6%A6%82%E5%BF%B5-4) |
| 26 | + - [实现](#%E5%AE%9E%E7%8E%B0-5) |
21 | 27 |
|
22 | 28 | <!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
23 | 29 |
|
24 | 30 | # 栈
|
25 | 31 |
|
26 |
| -## 原理 |
| 32 | +## 概念 |
27 | 33 |
|
28 | 34 | 栈是一个线性结构,在计算机中是一个相当常见的数据结构。
|
29 | 35 |
|
@@ -90,7 +96,7 @@ var isValid = function (s) {
|
90 | 96 |
|
91 | 97 | # 队列
|
92 | 98 |
|
93 |
| -## 原理 |
| 99 | +## 概念 |
94 | 100 |
|
95 | 101 | 队列一个线性结构,特点是在某一端添加数据,在另一端删除数据,遵循先进先出的原则。
|
96 | 102 |
|
@@ -193,7 +199,7 @@ class SqQueue {
|
193 | 199 |
|
194 | 200 | # 链表
|
195 | 201 |
|
196 |
| -## 原理 |
| 202 | +## 概念 |
197 | 203 |
|
198 | 204 | 链表是一个线性结构,同时也是一个天然的递归结构。链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
|
199 | 205 |
|
@@ -557,7 +563,7 @@ _delect(node, v) {
|
557 | 563 |
|
558 | 564 | # Trie
|
559 | 565 |
|
560 |
| -## 原理 |
| 566 | +## 概念 |
561 | 567 |
|
562 | 568 | 在计算机科学,**trie**,又称**前缀树**或**字典树**,是一种有序树,用于保存关联数组,其中的键通常是字符串。
|
563 | 569 |
|
@@ -640,9 +646,63 @@ class Trie {
|
640 | 646 |
|
641 | 647 | # 并查集
|
642 | 648 |
|
643 |
| -## 原理 |
| 649 | +## 概念 |
644 | 650 |
|
| 651 | +并查集是一种特殊的树结构,用于处理一些不交集的合并及查询问题。该结构中每个节点都有一个父节点,如果只有当前一个节点,那么该节点的父节点指向自己。 |
645 | 652 |
|
| 653 | +这个结构中有两个重要的操作,分别是: |
| 654 | + |
| 655 | +- Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。 |
| 656 | +- Union:将两个子集合并成同一个集合。 |
| 657 | + |
| 658 | + |
646 | 659 |
|
647 | 660 | ## 实现
|
648 | 661 |
|
| 662 | +```js |
| 663 | +class DisjointSet { |
| 664 | + // 初始化样本 |
| 665 | + constructor(count) { |
| 666 | + // 初始化时,每个节点的父节点都是自己 |
| 667 | + this.parent = new Array(count) |
| 668 | + // 用于记录树的深度,优化搜索复杂度 |
| 669 | + this.rank = new Array(count) |
| 670 | + for (let i = 0; i < count; i++) { |
| 671 | + this.parent[i] = i |
| 672 | + this.rank[i] = 1 |
| 673 | + } |
| 674 | + } |
| 675 | + find(p) { |
| 676 | + // 寻找当前节点的父节点是否为自己,不是的话表示还没找到 |
| 677 | + // 开始进行路径压缩优化 |
| 678 | + // 假设当前节点父节点为 A |
| 679 | + // 将当前节点挂载到 A 节点的父节点上,达到压缩深度的目的 |
| 680 | + while (p != this.parent[p]) { |
| 681 | + this.parent[p] = this.parent[this.parent[p]] |
| 682 | + p = this.parent[p] |
| 683 | + } |
| 684 | + return p |
| 685 | + } |
| 686 | + isConnected(p, q) { |
| 687 | + return this.find(p) === this.find(q) |
| 688 | + } |
| 689 | + // 合并 |
| 690 | + union(p, q) { |
| 691 | + // 找到两个数字的父节点 |
| 692 | + let i = this.find(p) |
| 693 | + let j = this.find(q) |
| 694 | + if (i === j) return |
| 695 | + // 判断两棵树的深度,深度小的加到深度大的树下面 |
| 696 | + // 如果两棵树深度相等,那就无所谓怎么加 |
| 697 | + if (this.rank[i] < this.rank[j]) { |
| 698 | + this.parent[i] = j |
| 699 | + } else if (this.rank[i] > this.rank[j]) { |
| 700 | + this.parent[j] = i |
| 701 | + } else { |
| 702 | + this.parent[i] = j |
| 703 | + this.rank[j] += 1 |
| 704 | + } |
| 705 | + } |
| 706 | +} |
| 707 | +``` |
| 708 | + |
0 commit comments