赞
踩
1.1 原理:
通过重复遍历待排序序列,比较相邻元素的值,若发现逆序则交换,直到没有可交换的元素为止。
1.2 算法流程:
1.3 时间复杂度:
1.4 稳定性:
稳定
1.5 Java代码实现
- public void bubbleSort(int[] arr) {
- int n = arr.length;
- for (int i = 0; i < n-1; i++)
- for (int j = 0; j < n-i-1; j++)
- if (arr[j] > arr[j+1]) {
- // swap arr[j+1] and arr[j]
- int temp = arr[j];
- arr[j] = arr[j+1];
- arr[j+1] = temp;
- }
- }
2.1 原理
首先,在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
2.2 算法流程
2.3 时间复杂度
2.3 稳定性
不稳定
2.4 Java代码实现
- public void selectionSort(int[] arr) {
- int n = arr.length;
- for (int i = 0; i < n-1; i++) {
- int minIdx = i;
- for (int j = i+1; j < n; j++)
- if (arr[j] < arr[minIdx])
- minIdx = j;
- // Swap the found minimum element with the first element
- int temp = arr[minIdx];
- arr[minIdx] = arr[i];
- arr[i] = temp;
- }
- }
3.1 原理
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
3.2 算法流程
3.3 时间复杂度
3.4 稳定性
稳定
3.5 Java代码实现
- public void insertionSort(int[] arr) {
- int n = arr.length;
- for (int i=1; i<n; ++i) {
- int key = arr[i];
- int j = i-1;
- /* Move elements of arr[0..i-1], that are
- greater than key, to one position ahead
- of their current position */
- while (j>=0 && arr[j] > key) {
- arr[j+1] = arr[j];
- j = j-1;
- }
- arr[j+1] = key;
- }
- }
4.1 原理
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。首先将数据分为两半,分别对它们进行排序,然后将两个有序的部分合并在一起。
4.2 算法流程
4.3 时间复杂度
4.4 稳定性
稳定
4.5 Java代码实现
- public void mergeSort(int[] arr, int l, int r) {
- if (l < r) {
- // Find the middle point
- int m = (l+r)/2;
- // Sort first and second halves
- mergeSort(arr, l, m);
- mergeSort(arr , m+1, r);
- // Merge the sorted halves
- merge(arr, l, m, r);
- }
- }
-
- // Merges two subarrays of arr[].
- // First subarray is arr[l..m]
- // Second subarray is arr[m+1..r]
- void merge(int arr[], int l, int m, int r) {
- // Find sizes of two subarrays to be merged
- int n1 = m - l + 1;
- int n2 = r - m;
- /* Create temp arrays */
- int L[] = new int [n1];
- int R[] = new int [n2];
- /*Copy data to temp arrays*/
- for (int i=0; i<n1; ++i)
- L[i] = arr[l + i];
- for (int j=0; j<n2; ++j)
- R[j] = arr[m + 1+ j];
- /* Merge the temp arrays */
- // Initial indexes of first and second subarrays
- int i = 0, j = 0;
- // Initial index of merged subarry array
- int k = l;
- while (i < n1 && j < n2) {
- if (L[i] <= R[j]) {
- arr[k] = L[i];
- i++;
- }
- else {
- arr[k] = R[j];
- j++;
- }
- k++;
- }
- /* Copy remaining elements of L[] if any */
- while (i < n1) {
- arr[k] = L[i];
- i++;
- k++;
- }
- /* Copy remaining elements of R[] if any */
- while (j < n2) {
- arr[k] = R[j];
- j++;
- k++;
- }
- }
5.1 原理
快速排序使用分治法策略来把一个序列分为两个子序列。步骤为:
5.2 算法流程
5.3 时间复杂度
5.4 稳定性
不稳定
5.5 Java代码实现
- public void quickSort(int[] arr, int low, int high) {
- if (low < high) {
- /* pi is partitioning index, arr[pi] is
- now at right place */
- int pi = partition(arr, low, high);
- // Recursively sort elements before
- // partition and after partition
- quickSort(arr, low, pi-1);
- quickSort(arr, pi+1, high);
- }
- }
-
- int partition(int arr[], int low, int high) {
- int pivot = arr[high];
- int i = (low-1); // index of smaller element
- for (int j=low; j<high; j++) {
- // If current element is smaller than the pivot
- if (arr[j] < pivot) {
- i++;
- // swap arr[i] and arr[j]
- int temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
- }
- // swap arr[i+1] and arr[high] (or pivot)
- int temp = arr[i+1];
- arr[i+1] = arr[high];
- arr[high] = temp;
- return i+1;
- }
6.1 原理
堆排序是利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。
6.2 算法流程
6.3 时间复杂度
6.4 稳定性
不稳定
6.5 Java代码实现
- public void heapSort(int arr[]) {
- int n = arr.length;
- // Build heap (rearrange array)
- for (int i = n / 2 - 1; i >= 0; i--)
- heapify(arr, n, i);
- // One by one extract an element from heap
- for (int i=n-1; i>=0; i--) {
- // Move current root to end
- int temp = arr[0];
- arr[0] = arr[i];
- arr[i] = temp;
- // call max heapify on the reduced heap
- heapify(arr, i, 0);
- }
- }
-
- // To heapify a subtree rooted with node i which is
- // an index in arr[]. n is size of heap
- void heapify(int arr[], int n, int i) {
- int largest = i; // Initialize largest as root
- int l = 2*i + 1; // left = 2*i + 1
- int r = 2*i + 2; // right = 2*i + 2
- // If left child is larger than root
- if (l < n && arr[l] > arr[largest])
- largest = l;
- // If right child is larger than largest so far
- if (r < n && arr[r] > arr[largest])
- largest = r;
- // If largest is not root
- if (largest != i) {
- int swap = arr[i];
- arr[i] = arr[largest];
- arr[largest] = swap;
- // Recursively heapify the affected sub-tree
- heapify(arr, n, largest);
- }
- }
7.1 原理
希尔排序是插入排序的一种更高效的改进版本。希尔排序将整个序列分割成若干个子序列分别进行插入排序,从而达到使整个序列达到有序的目的。
7.2 算法流程
7.3 时间复杂度
7.4 稳定性
不稳定
7.5 Java代码实现
- public void shellSort(int[] arr) {
- int n = arr.length;
- for (int gap = n/2; gap > 0; gap /= 2) {
- for (int i = gap; i < n; i += 1) {
- int temp = arr[i];
- int j;
- for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
- arr[j] = arr[j - gap];
- arr[j] = temp;
- }
- }
- }
8.1 原理
计数排序是一种非比较排序算法,其核心思想是将输入的数据值转换为键存储在额外开辟的数组空间中。它是通过计算一个数组中每个值的出现次数来实现排序的,适用于一定范围内的整数排序。由于计数排序不是基于比较的,它可以达到比基于比较的排序算法更快的排序速度。
8.2 算法流程
8.3 时间复杂度
其中,(n) 是数组长度,(k) 是数组中数据的范围。
8.4 稳定性
计数排序是稳定的排序算法。
8.5 Java代码实现
- public class CountingSort {
- public static void countingSort(int[] arr) {
- if (arr.length == 0) return;
- // 寻找数组中的最大最小值
- int maxValue = arr[0], minValue = arr[0];
- for (int value : arr) {
- if (value > maxValue) maxValue = value;
- if (value < minValue) minValue = value;
- }
- // 计数数组
- int[] countArray = new int[maxValue - minValue + 1];
- for (int value : arr) {
- countArray[value - minValue]++;
- }
- // 根据计数数组,输出结果
- int index = 0;
- for (int i = 0; i < countArray.length; i++) {
- while (countArray[i] > 0) {
- arr[index++] = i + minValue;
- countArray[i]--;
- }
- }
- }
-
- public static void main(String[] args) {
- int[] arr = {4, 2, 2, 8, 3, 3, 1};
- countingSort(arr);
- for (int i : arr) {
- System.out.print(i + " ");
- }
- }
- }
原理:线性搜索是最基本的搜索算法,它从数据结构的一端开始,逐个检查每个元素,直到找到所需的元素或搜索完所有元素。
算法流程:
时间复杂度:(O(n))
适用场景:线性搜索适用于小规模数据集或无序数据集的搜索。它不要求数据预先排序,因此对于结构简单的搜索任务来说是一个简便的选择。
特点:简单直接,但效率低下,特别是在处理大量数据时。
Java代码实现:
- public int linearSearch(int[] arr, int target) {
- for (int i = 0; i < arr.length; i++) {
- if (arr[i] == target) {
- return i; // 返回找到的元素的索引
- }
- }
- return -1; // 如果没有找到,返回-1
- }
原理:二分搜索是一种在有序数组中查找特定元素的高效算法。它通过将目标值与数组中间元素比较,每次排除一半的搜索空间,从而缩小搜索范围。
算法流程:
时间复杂度:(O(\log n))
适用场景:二分搜索适用于有序数据集。它高效地在排序数组中查找元素,通过不断将搜索范围减半来快速定位目标值。
特点:需要数据预先排序,但搜索效率高,特别适合于大规模数据集。
Java代码实现:
- public int binarySearch(int[] arr, int target) {
- int left = 0;
- int right = arr.length - 1;
-
- while (left <= right) {
- int mid = left + (right - left) / 2;
-
- if (arr[mid] == target) {
- return mid; // 找到目标值,返回索引
- } else if (arr[mid] < target) {
- left = mid + 1; // 在右半部分继续搜索
- } else {
- right = mid - 1; // 在左半部分继续搜索
- }
- }
-
- return -1; // 没有找到目标值,返回-1
- }
原理:深度优先搜索是一种用于遍历或搜索树或图的算法。它从一个节点开始,沿着树的深度遍历树的分支,直到找到所需的节点为止。
算法流程:
时间复杂度:(O(V + E)),其中(V)是顶点数,(E)是边数。
适用场景:深度优先搜索适用于树和图的搜索问题,,如解决迷宫问题、路径查找、拓扑排序等。它通过尽可能深地搜索树的分支,直到找到解决方案或到达叶子节点。
特点:适用于目标路径较深或需要搜索所有可能路径的情况。可能需要大量内存,因为需要维护一个栈来存储遍历路径。
Java代码实现:
原理:广度优先搜索是另一种图和树的遍历算法,它从根节点开始,逐层遍历所有邻接的节点。
算法流程:
时间复杂度:(O(V + E))
适用场景:广度优先搜索也适用于树和图的搜索问题,特别是在需要找到最短路径或层次遍历时。例如,社交网络中的朋友推荐、最短路径问题等。
特点:适用于目标路径较短的情况。它需要维护一个队列来存储每一层的节点,可能会占用较多内存。
Java代码实现:
动态规划适用于具有重叠子问题和最优子结构性质的问题。它通常用于求解优化问题,比如寻找最大值或最小值,计数问题等。
使用场景:
典型应用:
动态规划的关键步骤:
原理:哈希表通过使用哈希函数将键映射到表中的一个位置来访问记录,以支持快速插入和搜索操作。
算法流程:
时间复杂度:平均情况下为 (O(1)),最坏情况(所有键都映射到同一个位置)为 (O(n))。
Java代码实现:Java中的HashMap
类提供了哈希表的实现。
- import java.util.HashMap;
-
- HashMap<Integer, String> map = new HashMap<>();
- map.put(1, "one"); // 插入
- String value = map.get(1); // 查找
原理:顺序索引查找是在有序数组中通过顺序遍历索引来查找元素的方法。
算法流程:
时间复杂度:(O(n))
Java代码实现:
- public int sequentialIndexLookup(int[] arr, int target) {
- for (int i = 0; i < arr.length; i++) {
- if (arr[i] == target) {
- return i; // 返回目标元素的索引
- }
- }
- return -1; // 如果没有找到,返回-1
- }
原理:二叉搜索树是一种特殊的二叉树,其中每个节点都含有一个键,并且每个节点的键都大于其左子树中任意节点的键,而小于其右子树中任意节点的键。
算法流程:
时间复杂度:平均情况下为 (O(\log n)),最坏情况(树退化为链表)为 (O(n))。
Java代码实现:
- class TreeNode {
- int val;
- TreeNode left, right;
-
- TreeNode(int x) {
- val = x;
- }
- }
-
- public class BinarySearchTree {
- public TreeNode search(TreeNode root, int target) {
- if (root == null || root.val == target) return root;
- if (target < root.val) return search(root.left, target);
- else return search(root.right, target);
- }
- }
常用的哈希算法有多种,它们在安全性、效率、输出长度等方面有所不同,主要用于数据的快速查找、数据完整性验证、安全加密等。
字符串匹配算法在计算机科学中非常重要,特别是在文本编辑、搜索引擎、数据库管理、生物信息学等领域。
动态规划是解决优化问题的一种方法,它将复杂问题分解为更小的子问题,并存储这些子问题的解,以避免重复计算。动态规划广泛应用于各种领域,如算法设计、运筹学、人工智能等。
分治算法是一种重要的算法设计策略,它将一个复杂的问题分解成两个或多个相似的子问题,直到这些子问题变得简单足以直接求解。然后,这些子问题的解被合并为原问题的解。
贪心算法是一种在每一步选择中都采取当前状态下最优的选择,以期望通过局部最优的选择达到全局最优解的算法策略。它不像动态规划那样考虑整个问题的所有可能解,而是依赖于贪心选择性质,即通过局部最优选择能够产生全局最优解。
回溯算法是一种通过尝试分步的方式寻找问题的解决方法的算法。在每一步中,当它意识到当前的选择序列不会导致一个最终解时,它将取消最近的选择,尝试下一个选项。这种方法被广泛用于解决约束满足问题,其中包括搜索、组合优化问题等。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。