前端算法学习

一. 递归算法
递归算法是一种解决问题的有效方法,尤其是在处理嵌套结构的数据时。例如,在处理DOM树、解析JSON数据等方面,递归算法都有广泛的应用

// 计算一个数的阶乘
function fn(n){
if(n === 1) {
return 1
}
return n*fn(n-1)
}
// 说明 递归终止条件, 当n为1时,只返回 1,后续不再调用自身

二. 排序算法
排序算法在计算机科学中是非常基础和重要的概念。它们被用于将数据元素按照某种顺序(通常是升序或降序)进行排列。

1. 冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

function bubbleSort(arr) {
  let len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) { // 相邻元素两两对比
        let temp = arr[j + 1]; // 元素交换
        arr[j + 1] = arr[j];
        arr[j] = temp;
      }
    }
  }
  return arr;
}

let arr = [34, 8, 64, 51, 32, 21];
console.log(bubbleSort(arr)); // [8, 21, 32, 34, 51, 64]

2. 选择排序(Selection Sort)

选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

function selectionSort(arr) {
  let len = arr.length;
  let minIndex, temp;
  for (let i = 0; i < len - 1; i++) {
    minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    temp = arr[i];
    arr[i] = arr[minIndex];
    arr[minIndex] = temp;
  }
  return arr;
}

let arr = [34, 8, 64, 51, 32, 21];
console.log(selectionSort(arr)); // [8, 21, 32, 34, 51, 64]

3. 插入排序(Insertion Sort)

插入排序的工作方式是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

function insertionSort(arr) {
  let len = arr.length;
  let preIndex, current;
  for (let i = 1; i < len; i++) {
    preIndex = i - 1;
    current = arr[i];
    while (preIndex >= 0 && arr[preIndex] > current) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = current;
  }
  return arr;
}

let arr = [34, 8, 64, 51, 32, 21];
console.log(insertionSort(arr)); // [8, 21, 32, 34, 51, 64]

4. 快速排序(Quick Sort)

快速排序是一种分而治之的排序算法。它选择一个元素作为“基准”(pivot),然后将数组分成两个子数组:一个包含比基准小的元素,另一个包含比基准大的元素。然后对这两个子数组进行快速排序。

function quickSort(arr) {
  if (arr.length <= 1) return arr;
  let pivotIndex = Math.floor(arr.length / 2);
  let pivot = arr.splice(pivotIndex, 1)[0];
  let left = [];
  let right = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return quickSort(left).concat([pivot], quickSort(right));
}

let arr = [34, 8, 64, 51, 32, 21];
console.log(quickSort(arr)); // [8, 21, 32, 34, 51, 64]

5. 归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。

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

function merge(left, right) {
  let result = [];
  while (left.length && right.length) {
    if (left[0] <= right[0]) {
      result.push(left.shift());
    } else {
      result.push(right.shift());
    }
  }
  while (left.length) {
    result.push(left.shift());
  }
  while (right.length) {
    result.push(right.shift());
  }
  return result;
}

let arr = [34, 8, 64, 51, 32, 21];
console.log(mergeSort(arr)); // [8, 21, 32, 34, 51, 64]

冒泡排序和选择排序在数据量小的时候简单且有效,但在大数据量下效率较低。插入排序对于部分有序的数据集效率较高。快速排序和归并排序在处理大数据集时表现出色,但快速排序在最坏情况下的时间复杂度为O(n^2),而归并排序的时间复杂度始终为O(n log n)。
在实际的前端开发中,排序算法可能用于优化渲染列表、处理用户输入数据、进行数据库查询结果的排序等场景。选择哪种排序算法取决于具体的需求和场景。

三.查找算法
查找算法是计算机科学中的一个基础概念,用于在数据结构(如数组、列表、树、图等)中快速找到特定的元素。不同的查找算法在不同的数据结构和场景下有不同的效率。

1. 线性查找(Linear Search)

线性查找是最简单直观的查找算法。它按顺序逐个比较数据集中的每一个元素,直到找到目标元素或者搜索完整个数据集。

function linearSearch(arr, target) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === target) {
      return i; // 返回目标元素的索引
    }
  }
  return -1; // 如果没有找到目标元素,返回-1
}

let arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
let target = 5;
console.log(linearSearch(arr, target)); // 输出目标元素的索引,例如:4 或 7 或 9

2. 二分查找(Binary Search)

二分查找是一种高效的查找算法,它要求数据集必须是有序的。算法每次比较中间元素,如果中间元素正好是目标值,则搜索结束;如果目标值小于中间元素,则在左半部分继续搜索;反之则在右半部分继续搜索。

function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    if (arr[mid] === target) {
      return mid; // 返回目标元素的索引
    }
    if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return -1; // 如果没有找到目标元素,返回-1
}

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let target = 5;
console.log(binarySearch(arr, target)); // 输出目标元素的索引,例如:4

3. 哈希查找(Hash Search)

哈希查找利用哈希表(一种特殊的数据结构)来实现快速查找。哈希表通过哈希函数将键映射到存储位置,从而可以直接访问对应的值。
在JavaScript中,对象本质上是一个哈希表,键是唯一的,并且可以通过键直接访问对应的值。

let hashTable = {
  "apple": "fruit",
  "banana": "fruit",
  "carrot": "vegetable"
};

function hashSearch(hashTable, key) {
  if (hashTable.hasOwnProperty(key)) {
    return hashTable[key]; // 返回与键对应的值
  }
  return null; // 如果没有找到键,返回null
}

console.log(hashSearch(hashTable, "apple")); // 输出:"fruit"

4. 树查找

树查找算法通常用于在树形数据结构中查找元素,如二叉搜索树(Binary Search Tree)。
在二叉搜索树中,每个节点包含一个值,并且对于树中的每个节点,其左子树中的所有值都小于或等于该节点的值,而右子树中的所有值都大于或等于该节点的值。这使得在树中查找元素变得非常高效。

下面是一个简单的二叉搜索树的查找实现:

class Node {
  constructor(value) {
    this.value = value;
    this.left = null;
    this.right = null;
  }
}

function searchBST(root, target) {
  if (root === null) {
    return false; // 树为空,未找到目标
  }
  if (root.value === target) {
    return true; // 找到目标
  }
  if (root.value < target) {
    return searchBST(root.right, target); // 在右子树中继续查找
  }
  return searchBST(root.left, target); // 在左子树中继续查找
}

// 构建一个简单的二叉搜索树
let root = new Node(5);
root.left = new Node(3);
root.right = new Node(7);
root.left.left = new Node
(2);
root.left.right = new Node(4);
root.right.left = new Node(6);
root.right.right = new Node(8);

// 在二叉搜索树中查找目标值
let target = 6;
console.log(searchBST(root, target)); // 输出:true,表示找到了目标值

target = 9;
console.log(searchBST(root, target)); // 输出:false,表示未找到目标值

树查找还可以应用于其他类型的树,如AVL树、红黑树等,它们都是为了保持树的平衡而设计的,以确保查找、插入和删除操作的时间复杂度尽可能低。

5. 散列表查找(Hash Table Search)

散列表查找是一种基于哈希表实现的查找算法。它通过哈希函数将键映射到数组中的某个位置,从而可以快速访问对应的值。
在JavaScript中,你可以使用对象作为哈希表,键是唯一的,并且可以通过键直接访问对应的值。

// 创建一个哈希表
let hashTable = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
};

// 散列表查找函数
function hashTableSearch(hashTable, key) {
  if (hashTable.hasOwnProperty(key)) {
    return hashTable[key]; // 返回与键对应的值
  }
  return null; // 如果没有找到键,返回null
}

// 查找哈希表中的元素
console.log(hashTableSearch(hashTable, "key1")); // 输出:"value1"
console.log(hashTableSearch(hashTable, "key4")); // 输出:null

6. 字典树查找(Trie Search)

字典树(Trie)是一种特殊的树形数据结构,用于高效地存储和查找字符串数据集中的键。

class TrieNode {
  constructor() {
    this.children = {};
    this.isEndOfWord = false;
  }
}

class Trie {
  constructor() {
    this.root = new TrieNode();
  }

  insert(word) {
    let currentNode = this.root;
    for (let char of word) {
      if (!currentNode.children[char]) {
        currentNode.children[char] = new TrieNode();
      }
      currentNode = currentNode.children[char];
    }
    currentNode.isEndOfWord = true;
  }

  search(word) {
    let currentNode = this.root;
    for (let char of word) {
      if (!currentNode.children[char]) {
        return false;
      }
      currentNode = currentNode.children[char];
    }
    return currentNode.isEndOfWord;
  }
}

// 使用字典树查找
let trie = new Trie();
trie.insert("hello");
trie.insert("world");

console.log(trie.search("hello")); // 输出:true
console.log(trie.search("world")); // 输出:true
console.log(trie.search("hi")); // 输出:false

以上介绍了几种常见的查找算法,每种算法都有其适用的场景和优缺点。在实际应用中,需要根据具体的需求和数据结构的特点来选择合适的查找算法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值