Compare commits

..

9 Commits

Author SHA1 Message Date
Oleksii Trekhleb
0ca57d1e02
Merge branch 'master' into master 2024-07-13 21:07:28 +02:00
Mahdi Azarboon
9046d80bdb
Update README.md (#1141)
Before diving into any of the data structures, readers should be reminded of two fundamental laws in software architecture:

1.Everything is a trade-ff
2."Why is more important than the how"

So, readers face the nuances and reality of these data structures from the beginning. These two laws are coined by two thought leaders in software architecture: Mark Richards and Neal Ford. They have explained these two laws in various conference talks and books. For example, here you can read about these two laws here:

https://www.infoq.com/podcasts/software-architecture-hard-parts/


Also, here is a book for reference:
https://a.co/d/fKOodW9

Co-authored-by: Oleksii Trekhleb <3000285+trekhleb@users.noreply.github.com>
2024-07-13 20:58:45 +02:00
Alexander Cyon
e5b5944c68
Fix four typos (#1139) 2024-07-13 20:56:39 +02:00
Oleksii Trekhleb
2c67b48c21
Ad hoc versions of MinHeap, MaxHeap, and DisjointSet (#1117)
* Add DisjointSetMinimalistic

* Add MinHeapMinimalistic and MaxHeapMinimalistic

* Rename minimalistic to adhoc

* Update README
2024-03-09 17:15:19 +01:00
Mira Kwak
ac78353e3c
feat: added korean translation for trie (#1071)
Co-authored-by: Oleksii Trekhleb <trehleb@gmail.com>
2024-03-09 17:13:54 +01:00
irene (Irene Tomaini)
8959566a36
fix binary search typo (#1079)
Co-authored-by: Oleksii Trekhleb <trehleb@gmail.com>
2024-03-09 17:11:53 +01:00
Vi Truong
729bc4d78a
Add Vietnamese translation for LinkedList (#1086)
* translate readme from linked list

* add linked list for viet sub

---------

Co-authored-by: Oleksii Trekhleb <trehleb@gmail.com>
2024-03-09 17:09:21 +01:00
Vi Truong
8d1f473610
Vietsub (#1088)
* translate readme from linked list

* add linked list for viet sub

* add vietnamese readme translation for queue

* add readme in vietnamese for Stack
2024-03-09 17:06:47 +01:00
Arpit Goyal
111ea3dbd3
Update README.md (#1093) 2024-03-09 17:02:29 +01:00
20 changed files with 785 additions and 7 deletions

View File

@ -49,6 +49,8 @@ be accessed and modified efficiently. More precisely, a data structure is a coll
values, the relationships among them, and the functions or operations that can be applied to
the data.
Remember that each data has its own trade-offs. And you need to pay attention more to why you're choosing a certain data structure than to how to implement it.
`B` - Beginner, `A` - Advanced
* `B` [Linked List](src/data-structures/linked-list)

View File

@ -11,7 +11,7 @@ import Comparator from '../../../utils/comparator/Comparator';
export default function binarySearch(sortedArray, seekElement, comparatorCallback) {
// Let's create comparator from the comparatorCallback function.
// Comparator object will give us common comparison methods like equal() and lessThen().
// Comparator object will give us common comparison methods like equal() and lessThan().
const comparator = new Comparator(comparatorCallback);
// These two indices will contain current array (sub-array) boundaries.

View File

@ -46,7 +46,7 @@ Let's say we have an array of prices `[7, 6, 4, 3, 1]` and we're on the _1st_ da
1. _Option 1: Keep the money_ → profit would equal to the profit from buying/selling the rest of the stocks → `keepProfit = profit([6, 4, 3, 1])`.
2. _Option 2: Buy/sell at current price_ → profit in this case would equal to the profit from buying/selling the rest of the stocks plus (or minus, depending on whether we're selling or buying) the current stock price → `buySellProfit = -7 + profit([6, 4, 3, 1])`.
The overall profit would be equal to → `overalProfit = Max(keepProfit, buySellProfit)`.
The overall profit would be equal to → `overallProfit = Max(keepProfit, buySellProfit)`.
As you can see the `profit([6, 4, 3, 1])` task is being solved in the same recursive manner.

View File

@ -59,7 +59,7 @@ and return false.
queen here leads to a solution.
b) If placing queen in [row, column] leads to a solution then return
true.
c) If placing queen doesn't lead to a solution then umark this [row,
c) If placing queen doesn't lead to a solution then unmark this [row,
column] (Backtrack) and go to step (a) to try other rows.
3) If all rows have been tried and nothing worked, return false to trigger
backtracking.

View File

@ -93,7 +93,7 @@ three factors: the size of the bloom filter, the
number of hash functions we use, and the number
of items that have been inserted into the filter.
The formula to calculate probablity of a false positive is:
The formula to calculate probability of a false positive is:
( 1 - e <sup>-kn/m</sup> ) <sup>k</sup>

View File

@ -0,0 +1,78 @@
/**
* The minimalistic (ad hoc) version of a DisjointSet (or a UnionFind) data structure
* that doesn't have external dependencies and that is easy to copy-paste and
* use during the coding interview if allowed by the interviewer (since many
* data structures in JS are missing).
*
* Time Complexity:
*
* - Constructor: O(N)
* - Find: O(α(N))
* - Union: O(α(N))
* - Connected: O(α(N))
*
* Where N is the number of vertices in the graph.
* α refers to the Inverse Ackermann function.
* In practice, we assume it's a constant.
* In other words, O(α(N)) is regarded as O(1) on average.
*/
class DisjointSetAdhoc {
/**
* Initializes the set of specified size.
* @param {number} size
*/
constructor(size) {
// The index of a cell is an id of the node in a set.
// The value of a cell is an id (index) of the root node.
// By default, the node is a parent of itself.
this.roots = new Array(size).fill(0).map((_, i) => i);
// Using the heights array to record the height of each node.
// By default each node has a height of 1 because it has no children.
this.heights = new Array(size).fill(1);
}
/**
* Finds the root of node `a`
* @param {number} a
* @returns {number}
*/
find(a) {
if (a === this.roots[a]) return a;
this.roots[a] = this.find(this.roots[a]);
return this.roots[a];
}
/**
* Joins the `a` and `b` nodes into same set.
* @param {number} a
* @param {number} b
* @returns {number}
*/
union(a, b) {
const aRoot = this.find(a);
const bRoot = this.find(b);
if (aRoot === bRoot) return;
if (this.heights[aRoot] > this.heights[bRoot]) {
this.roots[bRoot] = aRoot;
} else if (this.heights[aRoot] < this.heights[bRoot]) {
this.roots[aRoot] = bRoot;
} else {
this.roots[bRoot] = aRoot;
this.heights[aRoot] += 1;
}
}
/**
* Checks if `a` and `b` belong to the same set.
* @param {number} a
* @param {number} b
*/
connected(a, b) {
return this.find(a) === this.find(b);
}
}
export default DisjointSetAdhoc;

View File

@ -19,6 +19,11 @@ _MakeSet_ creates 8 singletons.
After some operations of _Union_, some sets are grouped together.
## Implementation
- [DisjointSet.js](./DisjointSet.js)
- [DisjointSetAdhoc.js](./DisjointSetAdhoc.js) - The minimalistic (ad hoc) version of a DisjointSet (or a UnionFind) data structure that doesn't have external dependencies and that is easy to copy-paste and use during the coding interview if allowed by the interviewer (since many data structures in JS are missing).
## References
- [Wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)

View File

@ -0,0 +1,50 @@
import DisjointSetAdhoc from '../DisjointSetAdhoc';
describe('DisjointSetAdhoc', () => {
it('should create unions and find connected elements', () => {
const set = new DisjointSetAdhoc(10);
// 1-2-5-6-7 3-8-9 4
set.union(1, 2);
set.union(2, 5);
set.union(5, 6);
set.union(6, 7);
set.union(3, 8);
set.union(8, 9);
expect(set.connected(1, 5)).toBe(true);
expect(set.connected(5, 7)).toBe(true);
expect(set.connected(3, 8)).toBe(true);
expect(set.connected(4, 9)).toBe(false);
expect(set.connected(4, 7)).toBe(false);
// 1-2-5-6-7 3-8-9-4
set.union(9, 4);
expect(set.connected(4, 9)).toBe(true);
expect(set.connected(4, 3)).toBe(true);
expect(set.connected(8, 4)).toBe(true);
expect(set.connected(8, 7)).toBe(false);
expect(set.connected(2, 3)).toBe(false);
});
it('should keep the height of the tree small', () => {
const set = new DisjointSetAdhoc(10);
// 1-2-6-7-9 1 3 4 5
set.union(7, 6);
set.union(1, 2);
set.union(2, 6);
set.union(1, 7);
set.union(9, 1);
expect(set.connected(1, 7)).toBe(true);
expect(set.connected(6, 9)).toBe(true);
expect(set.connected(4, 9)).toBe(false);
expect(Math.max(...set.heights)).toBe(3);
});
});

View File

@ -279,7 +279,7 @@ export default class Heap {
/* istanbul ignore next */
pairIsInCorrectOrder(firstElement, secondElement) {
throw new Error(`
You have to implement heap pair comparision method
You have to implement heap pair comparison method
for ${firstElement} and ${secondElement} values.
`);
}

View File

@ -0,0 +1,115 @@
/**
* The minimalistic (ad hoc) version of a MaxHeap data structure that doesn't have
* external dependencies and that is easy to copy-paste and use during the
* coding interview if allowed by the interviewer (since many data
* structures in JS are missing).
*/
class MaxHeapAdhoc {
constructor(heap = []) {
this.heap = [];
heap.forEach(this.add);
}
add(num) {
this.heap.push(num);
this.heapifyUp();
}
peek() {
return this.heap[0];
}
poll() {
if (this.heap.length === 0) return undefined;
const top = this.heap[0];
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.pop();
this.heapifyDown();
return top;
}
isEmpty() {
return this.heap.length === 0;
}
toString() {
return this.heap.join(',');
}
heapifyUp() {
let nodeIndex = this.heap.length - 1;
while (nodeIndex > 0) {
const parentIndex = this.getParentIndex(nodeIndex);
if (this.heap[parentIndex] >= this.heap[nodeIndex]) break;
this.swap(parentIndex, nodeIndex);
nodeIndex = parentIndex;
}
}
heapifyDown() {
let nodeIndex = 0;
while (
(
this.hasLeftChild(nodeIndex) && this.heap[nodeIndex] < this.leftChild(nodeIndex)
)
|| (
this.hasRightChild(nodeIndex) && this.heap[nodeIndex] < this.rightChild(nodeIndex)
)
) {
const leftIndex = this.getLeftChildIndex(nodeIndex);
const rightIndex = this.getRightChildIndex(nodeIndex);
const left = this.leftChild(nodeIndex);
const right = this.rightChild(nodeIndex);
if (this.hasLeftChild(nodeIndex) && this.hasRightChild(nodeIndex)) {
if (left >= right) {
this.swap(leftIndex, nodeIndex);
nodeIndex = leftIndex;
} else {
this.swap(rightIndex, nodeIndex);
nodeIndex = rightIndex;
}
} else if (this.hasLeftChild(nodeIndex)) {
this.swap(leftIndex, nodeIndex);
nodeIndex = leftIndex;
}
}
}
getLeftChildIndex(parentIndex) {
return (2 * parentIndex) + 1;
}
getRightChildIndex(parentIndex) {
return (2 * parentIndex) + 2;
}
getParentIndex(childIndex) {
return Math.floor((childIndex - 1) / 2);
}
hasLeftChild(parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heap.length;
}
hasRightChild(parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heap.length;
}
leftChild(parentIndex) {
return this.heap[this.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heap[this.getRightChildIndex(parentIndex)];
}
swap(indexOne, indexTwo) {
const tmp = this.heap[indexTwo];
this.heap[indexTwo] = this.heap[indexOne];
this.heap[indexOne] = tmp;
}
}
export default MaxHeapAdhoc;

View File

@ -0,0 +1,117 @@
/**
* The minimalistic (ad hoc) version of a MinHeap data structure that doesn't have
* external dependencies and that is easy to copy-paste and use during the
* coding interview if allowed by the interviewer (since many data
* structures in JS are missing).
*/
class MinHeapAdhoc {
constructor(heap = []) {
this.heap = [];
heap.forEach(this.add);
}
add(num) {
this.heap.push(num);
this.heapifyUp();
}
peek() {
return this.heap[0];
}
poll() {
if (this.heap.length === 0) return undefined;
const top = this.heap[0];
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.pop();
this.heapifyDown();
return top;
}
isEmpty() {
return this.heap.length === 0;
}
toString() {
return this.heap.join(',');
}
heapifyUp() {
let nodeIndex = this.heap.length - 1;
while (nodeIndex > 0) {
const parentIndex = this.getParentIndex(nodeIndex);
if (this.heap[parentIndex] <= this.heap[nodeIndex]) break;
this.swap(parentIndex, nodeIndex);
nodeIndex = parentIndex;
}
}
heapifyDown() {
let nodeIndex = 0;
while (
(
this.hasLeftChild(nodeIndex)
&& this.heap[nodeIndex] > this.leftChild(nodeIndex)
)
|| (
this.hasRightChild(nodeIndex)
&& this.heap[nodeIndex] > this.rightChild(nodeIndex)
)
) {
const leftIndex = this.getLeftChildIndex(nodeIndex);
const rightIndex = this.getRightChildIndex(nodeIndex);
const left = this.leftChild(nodeIndex);
const right = this.rightChild(nodeIndex);
if (this.hasLeftChild(nodeIndex) && this.hasRightChild(nodeIndex)) {
if (left <= right) {
this.swap(leftIndex, nodeIndex);
nodeIndex = leftIndex;
} else {
this.swap(rightIndex, nodeIndex);
nodeIndex = rightIndex;
}
} else if (this.hasLeftChild(nodeIndex)) {
this.swap(leftIndex, nodeIndex);
nodeIndex = leftIndex;
}
}
}
getLeftChildIndex(parentIndex) {
return 2 * parentIndex + 1;
}
getRightChildIndex(parentIndex) {
return 2 * parentIndex + 2;
}
getParentIndex(childIndex) {
return Math.floor((childIndex - 1) / 2);
}
hasLeftChild(parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heap.length;
}
hasRightChild(parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heap.length;
}
leftChild(parentIndex) {
return this.heap[this.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heap[this.getRightChildIndex(parentIndex)];
}
swap(indexOne, indexTwo) {
const tmp = this.heap[indexTwo];
this.heap[indexTwo] = this.heap[indexOne];
this.heap[indexOne] = tmp;
}
}
export default MinHeapAdhoc;

View File

@ -58,6 +58,11 @@ Where:
> In this repository, the [MaxHeap.js](./MaxHeap.js) and [MinHeap.js](./MinHeap.js) are examples of the **Binary** heap.
## Implementation
- [MaxHeap.js](./MaxHeap.js) and [MinHeap.js](./MinHeap.js)
- [MaxHeapAdhoc.js](./MaxHeapAdhoc.js) and [MinHeapAdhoc.js](./MinHeapAdhoc.js) - The minimalistic (ad hoc) version of a MinHeap/MaxHeap data structure that doesn't have external dependencies and that is easy to copy-paste and use during the coding interview if allowed by the interviewer (since many data structures in JS are missing).
## References
- [Wikipedia](https://en.wikipedia.org/wiki/Heap_(data_structure))

View File

@ -0,0 +1,91 @@
import MaxHeap from '../MaxHeapAdhoc';
describe('MaxHeapAdhoc', () => {
it('should create an empty max heap', () => {
const maxHeap = new MaxHeap();
expect(maxHeap).toBeDefined();
expect(maxHeap.peek()).toBe(undefined);
expect(maxHeap.isEmpty()).toBe(true);
});
it('should add items to the heap and heapify it up', () => {
const maxHeap = new MaxHeap();
maxHeap.add(5);
expect(maxHeap.isEmpty()).toBe(false);
expect(maxHeap.peek()).toBe(5);
expect(maxHeap.toString()).toBe('5');
maxHeap.add(3);
expect(maxHeap.peek()).toBe(5);
expect(maxHeap.toString()).toBe('5,3');
maxHeap.add(10);
expect(maxHeap.peek()).toBe(10);
expect(maxHeap.toString()).toBe('10,3,5');
maxHeap.add(1);
expect(maxHeap.peek()).toBe(10);
expect(maxHeap.toString()).toBe('10,3,5,1');
maxHeap.add(1);
expect(maxHeap.peek()).toBe(10);
expect(maxHeap.toString()).toBe('10,3,5,1,1');
expect(maxHeap.poll()).toBe(10);
expect(maxHeap.toString()).toBe('5,3,1,1');
expect(maxHeap.poll()).toBe(5);
expect(maxHeap.toString()).toBe('3,1,1');
expect(maxHeap.poll()).toBe(3);
expect(maxHeap.toString()).toBe('1,1');
});
it('should poll items from the heap and heapify it down', () => {
const maxHeap = new MaxHeap();
maxHeap.add(5);
maxHeap.add(3);
maxHeap.add(10);
maxHeap.add(11);
maxHeap.add(1);
expect(maxHeap.toString()).toBe('11,10,5,3,1');
expect(maxHeap.poll()).toBe(11);
expect(maxHeap.toString()).toBe('10,3,5,1');
expect(maxHeap.poll()).toBe(10);
expect(maxHeap.toString()).toBe('5,3,1');
expect(maxHeap.poll()).toBe(5);
expect(maxHeap.toString()).toBe('3,1');
expect(maxHeap.poll()).toBe(3);
expect(maxHeap.toString()).toBe('1');
expect(maxHeap.poll()).toBe(1);
expect(maxHeap.toString()).toBe('');
expect(maxHeap.poll()).toBe(undefined);
expect(maxHeap.toString()).toBe('');
});
it('should heapify down through the right branch as well', () => {
const maxHeap = new MaxHeap();
maxHeap.add(3);
maxHeap.add(12);
maxHeap.add(10);
expect(maxHeap.toString()).toBe('12,3,10');
maxHeap.add(11);
expect(maxHeap.toString()).toBe('12,11,10,3');
expect(maxHeap.poll()).toBe(12);
expect(maxHeap.toString()).toBe('11,3,10');
});
});

View File

@ -0,0 +1,91 @@
import MinHeapAdhoc from '../MinHeapAdhoc';
describe('MinHeapAdhoc', () => {
it('should create an empty min heap', () => {
const minHeap = new MinHeapAdhoc();
expect(minHeap).toBeDefined();
expect(minHeap.peek()).toBe(undefined);
expect(minHeap.isEmpty()).toBe(true);
});
it('should add items to the heap and heapify it up', () => {
const minHeap = new MinHeapAdhoc();
minHeap.add(5);
expect(minHeap.isEmpty()).toBe(false);
expect(minHeap.peek()).toBe(5);
expect(minHeap.toString()).toBe('5');
minHeap.add(3);
expect(minHeap.peek()).toBe(3);
expect(minHeap.toString()).toBe('3,5');
minHeap.add(10);
expect(minHeap.peek()).toBe(3);
expect(minHeap.toString()).toBe('3,5,10');
minHeap.add(1);
expect(minHeap.peek()).toBe(1);
expect(minHeap.toString()).toBe('1,3,10,5');
minHeap.add(1);
expect(minHeap.peek()).toBe(1);
expect(minHeap.toString()).toBe('1,1,10,5,3');
expect(minHeap.poll()).toBe(1);
expect(minHeap.toString()).toBe('1,3,10,5');
expect(minHeap.poll()).toBe(1);
expect(minHeap.toString()).toBe('3,5,10');
expect(minHeap.poll()).toBe(3);
expect(minHeap.toString()).toBe('5,10');
});
it('should poll items from the heap and heapify it down', () => {
const minHeap = new MinHeapAdhoc();
minHeap.add(5);
minHeap.add(3);
minHeap.add(10);
minHeap.add(11);
minHeap.add(1);
expect(minHeap.toString()).toBe('1,3,10,11,5');
expect(minHeap.poll()).toBe(1);
expect(minHeap.toString()).toBe('3,5,10,11');
expect(minHeap.poll()).toBe(3);
expect(minHeap.toString()).toBe('5,11,10');
expect(minHeap.poll()).toBe(5);
expect(minHeap.toString()).toBe('10,11');
expect(minHeap.poll()).toBe(10);
expect(minHeap.toString()).toBe('11');
expect(minHeap.poll()).toBe(11);
expect(minHeap.toString()).toBe('');
expect(minHeap.poll()).toBe(undefined);
expect(minHeap.toString()).toBe('');
});
it('should heapify down through the right branch as well', () => {
const minHeap = new MinHeapAdhoc();
minHeap.add(3);
minHeap.add(12);
minHeap.add(10);
expect(minHeap.toString()).toBe('3,12,10');
minHeap.add(11);
expect(minHeap.toString()).toBe('3,11,10,12');
expect(minHeap.poll()).toBe(3);
expect(minHeap.toString()).toBe('10,11,12');
});
});

View File

@ -0,0 +1,155 @@
# Danh sách liên kết (Linked List)
_Đọc bằng ngôn ngữ khác:_
[_简体中文_](README.zh-CN.md),
[_Русский_](README.ru-RU.md),
[_日本語_](README.ja-JP.md),
[_Português_](README.pt-BR.md),
[_한국어_](README.ko-KR.md),
[_Español_](README.es-ES.md),
[_Türkçe_](README.tr-TR.md),
[_Українська_](README.uk-UA.md)
Trong khoa học máy tính, một danh sách liên kết là một bộ sưu tập tuyến tính
các phần tử dữ liệu, trong đó thứ tự tuyến tính không được xác định bởi
vị trí vật lý của chúng trong bộ nhớ. Thay vào đó, mỗi
phần tử trỏ đến phần tử tiếp theo. Đây là một cấu trúc dữ liệu
bao gồm một nhóm các nút cùng đại diện cho
một chuỗi. Dưới dạng đơn giản nhất, mỗi nút
bao gồm dữ liệu và một tham chiếu (nói cách khác,
một liên kết) đến nút tiếp theo trong chuỗi. Cấu trúc này
cho phép việc chèn hoặc loại bỏ các phần tử một cách hiệu quả
từ bất kỳ vị trí nào trong chuỗi trong quá trình lặp.
Các biến thể phức tạp hơn thêm các liên kết bổ sung, cho phép
việc chèn hoặc loại bỏ một cách hiệu quả từ bất kỳ phần tử nào
trong chuỗi dựa trên tham chiếu. Một nhược điểm của danh sách liên kết
là thời gian truy cập tuyến tính (và khó điều chỉnh). Truy cập nhanh hơn,
như truy cập ngẫu nhiên, là không khả thi. Mảng
có độ tương phản cache tốt hơn so với danh sách liên kết.
![Linked List](./images/linked-list.jpeg)
*Được làm từ [okso.app](https://okso.app)*
## Mã giải (Pseudocode) cho Các Hoạt Động Cơ Bản
*head = đầu,
*tail = đuôi,
*next = kế tiếp,
*node = nút,
*value = giá trị
### Chèn (Insert)
```
ThêmGiáTrị(giá trị) (Add(value))
Trước(Pre): giá trị là giá trị muốn thêm vào danh sách
Sau(Post): giá trị đã được đặt ở cuối danh sách
n ← node(value)
if head = ø
head ← n
tail ← n
else
tail.next ← n
tail ← n
end if
end ThêmGiáTrị(Add)
```
```
ChènVàoĐầu(giá trị)
Trước(Pre): giá trị là giá trị muốn thêm vào danh sách
Sau(Post): giá trị đã được đặt ở đầu danh sách
n ← node(value)
n.next ← head
head ← n
if tail = ø
tail ← n
end
end ChènVàoĐầu
```
### Tìm Kiếm (Search)
```
Chứa(đầu, giá trị)
Trước: đầu là nút đầu trong danh sách
giá trị là giá trị cần tìm kiếm
Sau: mục đó có thể ở trong danh sách liên kết, true; nếu không, là false
n ← head
while n != ø and n.value != value
n ← n.next
end while
if n = ø
return false
end if
return true
end Contains
```
### Xóa (Delete)
```
Xóa(đầu, giá trị)
Trước: đầu là nút đầu trong danh sách
giá trị là giá trị cần xóa khỏi danh sách
Sau: giá trị đã được xóa khỏi danh sách, true; nếu không, là false
if head = ø
return false
end if
n ← head
if n.value = value
if head = tail
head ← ø
tail ← ø
else
head ← head.next
end if
return true
end if
while n.next != ø and n.next.value != value
n ← n.next
end while
if n.next != ø
if n.next = tail
tail ← n
tail.next = null
else
n.next ← n.next.next
end if
return true
end if
return false
end Remove
```
### Duyệt(raverse)
Duyệt(đầu)
Trước: đầu là nút đầu trong danh sách
Sau: các mục trong danh sách đã được duyệt
n ← head
while n != ø
yield n.value
n ← n.next
end while
end Traverse
### Duyệt Ngược (Traverse in Reverse)
DuyệtNgược(đầu, đuôi)
Trước: đầu và đuôi thuộc cùng một danh sách
Sau: các mục trong danh sách đã được duyệt theo thứ tự ngược lại
## Độ Phức Tạp
### Độ Phức Tạp Thời Gian (Time Complexity)
| Access | Search | Insertion | Deletion |
| :-------: | :-------: | :-------: | :-------: |
| O(n) | O(n) | O(1) | O(n) |
## Độ Phức Tạp Không Gian (Space Complexity)
O(n)
## Tham Khảo
- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
- [YouTube](https://www.youtube.com/watch?v=njTh_OwMljA&index=2&t=1s&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)

View File

@ -0,0 +1,22 @@
# Hàng đợi (Queue)
_Đọc bằng ngôn ngữ khác:_
[_简体中文_](README.zh-CN.md),
[_Русский_](README.ru-RU.md),
[_日本語_](README.ja-JP.md),
[_Português_](README.pt-BR.md),
[_한국어_](README.ko-KR.md),
[_Українська_](README.uk-UA.md)
Trong khoa học máy tính, một **hàng đợi** là một loại cụ thể của kiểu dữ liệu trừu tượng hoặc bộ sưu tập trong đó các phần tử trong bộ sưu tập được giữ theo thứ tự và nguyên tắc (hoặc chỉ) các hoạt động trên bộ sưu tập là thêm các phần tử vào vị trí cuối cùng, được gọi là đưa vào hàng đợi (enqueue), và loại bỏ các phần tử từ vị trí đầu tiên, được gọi là đưa ra khỏi hàng đợi (dequeue). Điều này khiến cho hàng đợi trở thành một cấu trúc dữ liệu First-In-First-Out (FIFO). Trong cấu trúc dữ liệu FIFO, phần tử đầu tiên được thêm vào hàng đợi sẽ là phần tử đầu tiên được loại bỏ. Điều này tương đương với yêu cầu rằng sau khi một phần tử mới được thêm vào, tất cả các phần tử đã được thêm vào trước đó phải được loại bỏ trước khi có thể loại bỏ phần tử mới. Thường thì cũng có thêm một hoạt động nhìn hay lấy phần đầu, trả về giá trị của phần tử đầu tiên mà không loại bỏ nó. Hàng đợi là một ví dụ về cấu trúc dữ liệu tuyến tính, hoặc trừu tượng hơn là một bộ sưu tập tuần tự.
Hàng đợi FIFO (First-In-First-Out) có thể được biểu diễn như sau:
![Queue](./images/queue.jpeg)
*Made with [okso.app](https://okso.app)*
## Tham Khảo
- [Wikipedia](https://en.wikipedia.org/wiki/Queue_(abstract_data_type))
- [YouTube](https://www.youtube.com/watch?v=wjI1WNcIntg&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=3&)

View File

@ -0,0 +1,27 @@
# Ngăn xếp (stack)
_Đọc bằng ngôn ngữ khác:_
[_简体中文_](README.zh-CN.md),
[_Русский_](README.ru-RU.md),
[_日本語_](README.ja-JP.md),
[_Português_](README.pt-BR.md),
[_한국어_](README.ko-KR.md),
[_Español_](README.es-ES.md),
[_Українська_](README.uk-UA.md)
Trong khoa học máy tính, một ngăn xếp (stack) là một kiểu dữ liệu trừu tượng phục vụ như một bộ sưu tập các phần tử, với hai hoạt động chính:
đẩy (push), thêm một phần tử vào bộ sưu tập, và
lấy (pop), loại bỏ phần tử được thêm gần nhất mà chưa được loại bỏ.
Thứ tự mà các phần tử được lấy ra khỏi ngăn xếp dẫn đến tên gọi thay thế của nó, là LIFO (last in, first out). Ngoài ra, một hoạt động nhìn có thể cung cấp quyền truy cập vào phần trên mà không làm thay đổi ngăn xếp. Tên "ngăn xếp" cho loại cấu trúc này đến từ sự tương tự với một bộ sưu tập các vật phẩm vật lý được xếp chồng lên nhau, điều này làm cho việc lấy một vật phẩm ra khỏi đỉnh của ngăn xếp dễ dàng, trong khi để đến được một vật phẩm sâu hơn trong ngăn xếp có thể đòi hỏi việc lấy ra nhiều vật phẩm khác trước đó.
Biểu diễn đơn giản về thời gian chạy của một ngăn xếp với các hoạt động đẩy và lấy.
![Stack](./images/stack.jpeg)
*Made with [okso.app](https://okso.app)*
## Tham Khảo
- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
- [YouTube](https://www.youtube.com/watch?v=njTh_OwMljA&index=2&t=1s&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)

View File

@ -23,7 +23,7 @@ together with a list of references to nodes (the "children"),
with the constraints that no reference is duplicated, and none
points to the root.
A simple unordered tree; in this diagram, the node labeled 7 has
A simple unordered tree; in this diagram, the node labeled 3 has
two children, labeled 2 and 6, and one parent, labeled 2. The
root node, at the top, has no parent.

View File

@ -0,0 +1,19 @@
# Trie
_Read this in other languages:_
[_简体中文_](README.zh-CN.md),
[_Русский_](README.ru-RU.md),
[_Português_](README.pt-BR.md),
[_Українська_](README.uk-UA.md),
[_한국어_](README.ko-KO.md)
컴퓨터 과학에서 **트라이**는 디지털 트리라고도 불리며 때로는 기수 트리 또는 접두사 트리(접두사로 검색할 수 있기 때문에)라고도 불리며 일종의 검색 트리입니다. 키가 보통 문자열인 동적 집합 또는 연관 배열을 저장하는 데 사용되는 순서가 지정된 트리 데이터 구조입니다. 이진 검색 트리와 달리 트리의 어떤 노드도 해당 노드와 연결된 키를 저장하지 않으며 대신 트리의 위치가 해당 노드와 연결된 키를 정의합니다. 노드의 모든 하위 항목은 해당 노드와 연결된 문자열의 공통 접두사를 가지며 루트는 빈 문자열과 연결됩니다. 값은 모든 노드와 반드시 연결되지는 않습니다. 오히려 값은 나뭇잎과 관심 있는 키에 해당하는 일부 내부 노드에만 연결되는 경향이 있습니다. 접두사 트리의 공간에 최적화된 표현은 콤팩트 접두사 트리를 참조하십시오.
![Trie](./images/trie.jpg)
_Made with [okso.app](https://okso.app)_
## 참조
- [Wikipedia](<https://ko.wikipedia.org/wiki/%ED%8A%B8%EB%9D%BC%EC%9D%B4_(%EC%BB%B4%ED%93%A8%ED%8C%85)>)
- [YouTube](https://www.youtube.com/watch?v=zIjfhVPRZCg&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=7&t=0s)

View File

@ -4,7 +4,8 @@ _Read this in other languages:_
[_简体中文_](README.zh-CN.md),
[_Русский_](README.ru-RU.md),
[_Português_](README.pt-BR.md),
[_Українська_](README.uk-UA.md)
[_Українська_](README.uk-UA.md),
[_한국어_](README.ko-KO.md)
In computer science, a **trie**, also called digital tree and sometimes
radix tree or prefix tree (as they can be searched by prefixes),