10 种最佳排序算法原理及代码(1),2024年最新不愧是阿里大佬

function bucketSort(items) {
let buckets = new Array(items.length);
for (let i = 0; i < buckets.length; i++) {
buckets[i] = [];
}
for (let j = 0; j < items.length; j++) {
let bucket = Math.floor(items[j] / items.length);
buckets[bucket].push(items[j]);
}
for (let k = 0; k < buckets.length; k++) {
buckets[k].sort();
}
return [].concat(…buckets);
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(bucketSort(items));

5. Shell 排序

Shell 排序使用插入排序算法,但不是一次对整个列表排序,而是将列表分成更小的子列表。然后使用插入排序算法对这些子列表进行排序,从而减少排序列表所需的交换次数。

它的工作原理是首先定义一个称为增量序列的整数序列。增量序列用于确定将独立排序的子列表的大小。最常用的增量序列是“Knuth序列”,其定义如下(其中 h 为具有初始值的区间,n是列表的长度):

h = 1
while h < n:
h = 3*h + 1

一旦定义了自增序列,Shell 排序算法就会对元素的子列表进行排序。子列表使用插入排序算法排序,以增量序列作为步长。该算法对子列表进行排序,从最大的增量开始,然后迭代到最小的增量。

该算法在增量大小为 1 时停止,此时它相当于常规的插入排序算法。

A shellsort animation

Shell 排序的历史

Shell排序是由 Donald Shell 于 1959 年发明的,是插入排序的一种变体,旨在通过将原始列表分解成更小的子列表并对这些子列表独立排序来提高其性能。

Shell 排序的优点
  • 它是插入排序的泛化,因此易于理解和实现。
  • 它的时间复杂度比很多输入数据序列O(n^2) 都要好。
  • 它是一种就地排序算法,这意味着它不需要额外的内存。
Shell 排序的缺点

很难预测 Shell 排序的时间复杂度,因为它取决于增量序列的选择。

Shell 排序的用处

Shell 排序是一种通用算法,用于在各种应用程序中对数据进行排序,特别是在对大型数据集(利用快速排序桶排序)进行排序时。

  • 对主要排序的数据进行排序:Shell 排序减少了对数据进行排序所需的比较和交换次数。这使得它比其他排序算法(如快速排序归并排序)在特定情况下更快。
  • 对具有少量反转的数组进行排序:反转是衡量数组未排序程度的指标,定义为顺序错误的元素对数。在对具有少量反转的数组进行排序时,Shell 排序比其他一些算法(如冒泡排序插入排序)更有效。
  • **就地排序:**Shell 排序不需要额外的内存来对输入进行排序,使其成为就地排序的竞争者。这使得它在内存有限或不需要额外内存使用的情况下很有用。
  • **在分布式环境中进行排序:**通过将输入数据划分为较小的子列表并独立排序,可以在单独的处理器或节点上对每个子列表进行排序,从而减少对数据进行排序所需的时间。
Shell 排序的实现
Python Shell 排序代码示例

def shell_sort(items):
sublistcount = len(items)//2
while sublistcount > 0:
for start in range(sublistcount):
gap_insertion_sort(items, start, sublistcount)
sublistcount = sublistcount // 2
return items

def gap_insertion_sort(items, start, gap):
for i in range(start+gap, len(items), gap):
currentvalue = items[i]
position = i
while position >= gap and items[position-gap] > currentvalue:
items[position] = items[position-gap]
position = position-gap
items[position] = currentvalue

items = [6,20,8,19,56,23,87,41,49,53]
print(shell_sort(items))

Javascript Shell 排序代码示例

function shellSort(items) {
let sublistcount = Math.floor(items.length / 2);
while (sublistcount > 0) {
for (let start = 0; start < sublistcount; start++) {
gapInsertionSort(items, start, sublistcount);
}
sublistcount = Math.floor(sublistcount / 2);
}
return items;
}

function gapInsertionSort(items, start, gap) {
for (let i = start + gap; i < items.length; i += gap) {
let currentValue = items[i];
let position = i;
while (position >= gap && items[position - gap] > currentValue) {
items[position] = items[position - gap];
position = position - gap;
}
items[position] = currentValue;
}
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(shellSort(items));

6. 归并排序

归并排序的基本思想是将输入列表分成两半,使用归并排序对每一半进行递归排序,然后将已排序的两半合并回一起。合并步骤是通过重复比较每一半的第一个元素并将两个元素中较小的元素添加到排序列表中来执行的。这个过程不断重复,直到所有的元素都合并在一起。

An animation of the merge sort process

  1. 首先,将列表划分为最小的单元(一个元素),
  2. 然后将每个元素与相邻列表进行比较,对两个相邻列表进行排序和合并。
  3. 最后,对所有元素进行排序和合并。
归并排序的历史

归并排序是由约翰·冯·诺伊曼于 1945 年发明的,作为一种基于比较的排序算法,它通过将输入列表划分为更小的子列表,对这些子列表进行递归排序,然后将它们合并在一起产生最终排序列表。

归并排序的优点

在最坏的情况下,归并排序的时间复杂度为O(nlogn),这使得它比冒泡排序插入排序选择排序等其他流行的排序算法更有效。
归并排序也是一种算法,这意味着它保留相等元素的相对顺序。

归并排序的缺点

归并排序在内存使用方面有一些缺点。该算法在除法步骤中需要额外的内存来存储列表的两半,在合并步骤中需要额外的内存来存储最终排序的列表。在对非常大的列表进行排序时,这可能是一个问题。

归并排序的用处

归并排序是一种通用排序算法,可以并行化排序大型数据集和外部排序(如快速排序桶排序),它也通常用作更复杂算法(如冒泡排序插入排序)的基础。

  • **稳定的排序:**合并排序的稳定排序意味着它保留了相等元素的相对顺序。这使得它在保持相等元素的顺序很重要的情况下很有用,例如在金融应用程序中或出于可视化目的对数据进行排序时。
  • **实现二进制搜索:**它用于有效地搜索排序列表中的特定元素,因为它依赖于排序的输入。合并排序可用于有效地对二进制搜索和其他类似算法的输入进行排序。
归并排序的实现
  1. 使用递归将列表拆分为更小的排序子列表。
  2. 将子列表重新合并在一起,在合并时对项目进行比较和排序。
Python 归并排序代码示例

def merge_sort(items):
if len(items) <= 1:
return items

mid = len(items) // 2
left = items[:mid]
right = items[mid:]

left = merge_sort(left)
right = merge_sort(right)

return merge(left, right)

def merge(left, right):
merged = []
left_index = 0
right_index = 0

while left_index < len(left) and right_index < len(right):
if left[left_index] > right[right_index]:
merged.append(right[right_index])
right_index += 1
else:
merged.append(left[left_index])
left_index += 1

merged += left[left_index:]
merged += right[right_index:]

return merged

items = [6,20,8,19,56,23,87,41,49,53]
print(merge_sort(items))

Javascript 归并排序代码示例

function mergeSort(items) {
if (items.length <= 1) {
return items;
}
let mid = Math.floor(items.length / 2);
let left = items.slice(0, mid);
let right = items.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
let merged = [];
let leftIndex = 0;
let rightIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
if (left[leftIndex] > right[rightIndex]) {
merged.push(right[rightIndex]);
rightIndex++;
} else {
merged.push(left[leftIndex]);
leftIndex++;
}
}
return merged.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(mergeSort(items));

7. 选择排序

选择排序反复从列表的未排序部分中选择最小的元素,并将其与未排序部分的第一个元素交换。这个过程一直持续到整个列表排序完毕。

An animation showing how selection sort works

红色是当前最小值,黄色是排序列表,蓝色是当前项目。

选择排序的历史

选择排序是一种简单而直观的排序算法,从计算机科学的早期开始就存在了。类似的算法很可能是在 20 世纪 50 年代由研究人员独立开发的。
它是最早开发的排序算法之一,并且它仍然是用于教育目的和简单排序任务的流行算法。

选择排序的优点

选择排序在某些应用程序中使用,在这些应用程序中,简单性和易于实现比效率更重要。它还可以作为一种教学工具,用于向学生介绍排序算法及其属性,因为它易于理解和实现。

选择排序的缺点

尽管它很简单,但与其他排序算法(如归并排序快速排序)相比,选择排序不是很有效。它的最坏情况下的时间复杂度为 O(n^2),对大列表进行排序可能需要很长时间。
选择排序也不是一种稳定的排序算法,这意味着它可能无法保持相等元素的顺序。

选择排序的用处

选择排序类似于冒泡排序插入排序,因为它可以用来对小数据集进行排序,而且它的简单性也使它成为教育和学习排序算法的有用工具。其他用途包括:

  • **使用有限的内存对数据进行排序:**它只需要恒定量的额外内存来执行排序,因此在内存使用有限的情况下很有用。
  • **使用唯一值对数据进行排序:**它不依赖于主要排序的输入,因此对于具有唯一值的数据集来说,它是一个不错的选择,而其他排序算法可能必须执行额外的检查或优化。
选择排序的实现
  1. 遍历列表,选择最小的项。
  2. 将最小的项与当前位置项交换。
  3. 对列表的其余部分重复此过程。
Python 选择排序代码示例

def selection_sort(items):
for i in range(len(items)):
min_idx = i
for j in range(i+1, len(items)):
if items[min_idx] > items[j]:
min_idx = j
items[i], items[min_idx] = items[min_idx], items[i]
return items

items = [6,20,8,19,56,23,87,41,49,53]
print(selection_sort(items))

Javascript 选择排序代码示例

function selectionSort(items) {
let minIdx;

for (let i = 0; i < items.length; i++) {
minIdx = i;
for (let j = i + 1; j < items.length; j++) {
if (items[j] < items[minIdx]) {
minIdx = j;
}
}
let temp = items[i];
items[i] = items[minIdx];
items[minIdx] = temp;
}
return items;
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(selectionSort(items));

8. 基数排序

基数排序的基本思想是通过按被排序的数字或字符中的每个数字分组来对数据进行排序,从右到左或从左到右。对每个数字重复这个过程,得到一个排序列表。
其最坏情况性能为 O(w*cdotn),其中 n 为 key 数量,为 w 为键长度。

基数排序的历史

基数排序最早是由 Herman Hollerith 在 19 世纪末引入的,作为一种有效地对打孔卡片上的数据进行排序的方法,打孔卡片上的每一列代表数据中的一个数字。
后来,在 20 世纪中期,一些研究人员对它进行了改编和推广,通过按二进制表示中的每个比特对数据进行分组来对二进制数据进行排序。但它也用于对字符串数据进行排序,其中每个字符在排序中被视为数字。

近年来,基数排序作为并行和分布式计算环境的排序算法重新引起了人们的兴趣,因为它很容易并行化,并且可以用于以分布式方式对大型数据集进行排序。

一种 IBM 卡片分类器,对大量打孔卡片执行基数排序

基数排序的优点

基数排序是一种线性时间排序算法,这意味着它的时间复杂度与输入数据的大小成正比。这使得它成为对大型数据集进行排序的有效算法,尽管对于较小的数据集,它可能不如其他排序算法那么有效。

它的线性时间复杂度和稳定性使它成为对大型数据集排序的有用工具,它的并行性使它对分布式计算环境中的数据排序很有用。
基数排序也是一种稳定的排序算法,这意味着它保留相等元素的相对顺序。

基数排序的用处

基数排序可用于需要对大型数据集进行高效排序的各种应用程序。它对于排序字符串数据和固定长度的键特别有用,也可以用于并行和分布式计算环境。

并行处理:基数排序通常更适合于对大型数据集进行排序(优于归并排序快速排序桶排序)。像桶排序一样,基数可以有效地对字符串数据进行排序,这使得它适合于自然语言处理应用程序。
**用固定长度的键排序数据:**基数排序在对具有固定长度键的数据进行排序时特别有效,因为它可以通过每次检查每个键的一个数字来执行排序。

基数排序的实现
  1. 比较列表中每一项的数字。
  2. 按数字分组。
  3. 按大小对组进行排序。
  4. 递归地对每个组进行排序,直到每个项都在正确的位置。
Python 基数排序代码示例

def radix_sort(items):
max_length = False
tmp, placement = -1, 1

while not max_length:
max_length = True
buckets = [list() for _ in range(10)]

for i in items:
tmp = i // placement
buckets[tmp % 10].append(i)
if max_length and tmp > 0:
max_length = False

a = 0
for b in range(10):
buck = buckets[b]
for i in buck:
items[a] = i
a += 1

placement *= 10
return items

items = [6,20,8,19,56,23,87,41,49,53]
print(radix_sort(items))

Javascript 基数排序代码示例

function radixSort(items) {
let maxLength = false;
let tmp = -1;
let placement = 1;

while (!maxLength) {
maxLength = true;
let buckets = Array.from({ length: 10 }, () => []);

for (let i = 0; i < items.length; i++) {
tmp = Math.floor(items[i] / placement);
buckets[tmp % 10].push(items[i]);
if (maxLength && tmp > 0) {
maxLength = false;
}
}

let a = 0;
for (let b = 0; b < 10; b++) {
let buck = buckets[b];
for (let j = 0; j < buck.length; j++) {
items[a] = buck[j];
a++;
}
}

placement *= 10;
}
return items;
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(radixSort(items));

9. 梳子排序

梳子排序比较相隔一定距离的元素对,如果它们顺序不一致,就交换它们。对之间的距离最初设置为正在排序的列表的大小,然后在每次传递时减少一个因子(称为“收缩因子”),直到达到最小值 1。重复这个过程,直到列表被完全排序。

梳子排序算法类似于冒泡排序算法,但比较元素之间的间隙更大。这个较大的间隙允许较大的值更快地移动到列表中的正确位置。

An animation showing how comb sort takes place

梳子排序的历史

梳状排序算法是一种相对较新的排序算法,于 1980 年由 Włodzimierz Dobosiewicz 和Artur Borowy 首次提出。该算法的灵感来自于使用梳子理顺纠结的头发的想法,它使用类似的过程来理顺未排序的值列表。

梳子排序的优点

梳子排序的最坏情况时间复杂度为 O(n^2),但在实践中它通常比其他排序算法(如冒泡排序)快,因为它使用了收缩因子。收缩因子允许算法快速将大值移动到正确的位置,减少完全排序列表所需的传递次数。

梳子排序的用处

梳子排序是一种相对简单和有效的排序算法,在各种应用程序中:

  • 排序具有大范围值的数据:在比较元素之间使用更大的间距可以让更大的值更快地移动到列表中的正确位置。
  • 在实时应用程序中排序数据:梳子排序是一种稳定的排序算法,它保持了相等元素的相对顺序。这对于需要保留相等元素的顺序的实时应用程序中的数据排序非常有用。
  • 在内存受限的环境中排序数据:梳子排序不需要额外的内存来对数据进行排序。这对于在内存受限的环境中对数据进行排序非常有用,因为在这种环境中没有额外的内存可用。
梳子排序的实现
  1. 从列表之间最大长度开始。
  2. 比较间隔末端的项,如果顺序不对就交换它们。
  3. 减小间隙并重复此过程,直到间隙为 1
  4. 最后对剩下的项进行冒泡排序。
Python 梳子排序代码示例

def comb_sort(items):
gap = len(items)
shrink = 1.3
sorted = False
while not sorted:
gap //= shrink
if gap <= 1:
sorted = True
else:
for i in range(len(items)-gap):
if items[i] > items[i+gap]:
items[i],items[i+gap] = items[i+gap],items[i]
return bubble_sort(items)

def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items)-1-i):
if items[j] > items[j+1]:
items[j], items[j+1] = items[j+1], items[j]
return items

items = [6,20,8,19,56,23,87,41,49,53]
print(comb_sort(items))

Javascript 梳子排序代码示例

function combSort(items) {
let gap = items.length;
let shrink = 1.3;
let sorted = false;
while (!sorted) {
gap = Math.floor(gap / shrink);
if (gap <= 1) {
sorted = true;
} else {
for (let i = 0; i < items.length - gap; i++) {
if (items[i] > items[i + gap]) {
let temp = items[i];
items[i] = items[i + gap];
items[i + gap] = temp;
}
}
}
}
return bubbleSort(items);
}

function bubbleSort(items) {
let swapped;
do {
swapped = false;
for (let i = 0; i < items.length - 1; i++) {
if (items[i] > items[i + 1]) {
let temp = items[i];
items[i] = items[i + 1];
items[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
return items;
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(combSort(items));

10. Timsort

Timsort 算法的工作原理是将输入数据分成更小的子数组,然后使用插入排序对这些子数组进行排序。然后使用归并排序将这些排序的子数组组合起来,以产生一个完全排序的数组。

Timsort的最坏情况时间复杂度为 O(nlogn),这使得它对大型数据集的排序效率很高。它也是一种稳定的排序算法,这意味着它保留了相等元素的相对顺序。

Timsort 的历史

Timsort 是由 Tim Peters 在2002年为 Python 编程语言开发的。它是一种混合排序算法,结合使用插入排序和归并排序技术,旨在有效地对各种不同类型的数据进行排序。
由于它在处理不同类型数据方面的效率和通用性,它已经被其他几种编程语言所采用,包括Java和c#。

Timsort 的优点

Timsort 的一个关键特性是它能够有效地处理不同类型的数据。它通过检测“runs”来实现这一点,“runs”是已经排序的元素序列。Timsort 然后以一种最小化生成完全排序数组所需的比较和交换次数的方式组合这些运行。
Timsort 的另一个重要特性是它能够处理部分排序的数据。在这种情况下,Timsort 可以检测部分排序的区域,并使用插入排序对其进行快速排序,从而减少对数据进行完全排序所需的时间。

Timsort 的用处

作为一种高级算法,Timsort 可以用于在内存受限的系统上对数据进行排序。

编程语言中的排序:Timsort 通常被用作这些语言中的默认排序算法,因为它具有处理不同类型数据的效率和能力。
整理数据:Timsort 在对可能部分排序或包含已经排序的子数组的实际数据进行排序时特别高效,因为它能够检测这些运行并使用
插入排序
对它们进行快速排序,从而减少对数据进行完全排序所需的时间。

对不同类型的数据进行排序:它旨在有效地处理不同类型的数据,包括数字、字符串和自定义对象。它可以检测具有相同类型的数据运行,并使用归并排序有效地组合它们,减少所需的比较和交换次数。

Timsort 的实现
  1. 将一个未排序的列表分解成更小的、排序的子列表。
  2. 合并子列表以形成更大的排序列表。
  3. 重复这个过程,直到整个列表排序完毕。
Python Timsort代码示例

def insertion_sort(arr, left=0, right=None):
if right is None:
right = len(arr) - 1

for i in range(left + 1, right + 1):
key_item = arr[i]
j = i - 1
while j >= left and arr[j] > key_item:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key_item

return arr

def merge(left, right):
if not left:
return right

if not right:
return left

if left[0] < right[0]:
return [left[0]] + merge(left[1:], right)

return [right[0]] + merge(left, right[1:])

def timsort(arr):
min_run = 32
n = len(arr)

for i in range(0, n, min_run):
insertion_sort(arr, i, min((i + min_run - 1), n - 1))

size = min_run
while size < n:
for start in range(0, n, size * 2):
midpoint = start + size - 1
end = min((start + size * 2 - 1), (n-1))
merged_array = merge(
left=arr[start:midpoint + 1],
right=arr[midpoint + 1:end + 1]
)
arr[start:start + len(merged_array)] = merged_array

size *= 2

return arr

items = [6,20,8,19,56,23,87,41,49,53]
print(timsort(items))

Javascript Timsort代码示例

function insertionSort(arr, left = 0, right = arr.length - 1) {
for (let i = left + 1; i <= right; i++) {
const keyItem = arr[i];
let j = i - 1;
while (j >= left && arr[j] > keyItem) {
arr[j + 1] = arr[j];
j–;
}
arr[j + 1] = keyItem;
}
return arr;
}

function merge(left, right) {
let i = 0;
let j = 0;
const merged = [];

while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
merged.push(left[i]);
i++;
} else {
merged.push(right[j]);
j++;
}
}

return merged.concat(left.slice(i)).concat(right.slice(j));
}

function timsort(arr) {
const minRun = 32;
const n = arr.length;

for (let i = 0; i < n; i += minRun) {
insertionSort(arr, i, Math.min(i + minRun - 1, n - 1));
}

let size = minRun;
while (size < n) {
for (let start = 0; start < n; start += size * 2) {
const midpoint = start + size - 1;
const end = Math.min(start + size * 2 - 1, n - 1);
const merged = merge(
arr.slice(start, midpoint + 1),
arr.slice(midpoint + 1, end + 1)
);
arr.splice(start, merged.length, …merged);
}
size *= 2;
}

return arr;
}

let items = [6, 20, 8, 19, 56, 23, 87, 41, 49, 53];
console.log(timsort(items));

比较所有排序算法

请注意,表中列出的时间复杂度和空间复杂度是最坏情况复杂度,实际性能可能因具体实现和输入数据而异。

算法时间复杂度空间复杂性就地排序是否稳定自适应排序
冒泡排序O(n^2)O(1)
快速排序O(nlogn)O(logn)
桶排序O(n+k)O(n+k)
Shell 排序O(nlogn)$O(1)
归并排序$O(n \log n)$O(n)
选择排序$O(n^2)$O(1)
基数排序O(w*cdotn)O(w+n)
梳子排序O(n^2)O(1)
TimsortO(nlogn)O(n)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Timsort | O(nlogn) | O(n) | 是 | 是 | 是 |

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-NuLF6rlB-1712946981617)]
[外链图片转存中…(img-GvHCARnO-1712946981618)]
[外链图片转存中…(img-sIDH8mll-1712946981618)]
[外链图片转存中…(img-83PP8jVx-1712946981619)]
[外链图片转存中…(img-tZzJlKwH-1712946981619)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-VBSjS67V-1712946981620)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值