首页 > 编程语言 >经典算法掌握

经典算法掌握

时间:2024-03-13 10:29:35浏览次数:20  
标签:arr 掌握 int 复杂度 元素 算法 数组 经典 排序

排序算法是对一组数据按照特定规则进行排序的算法。常见的排序算法有冒泡排序、插入排序、选择排序、快速排序和归并排序等。

  1. 冒泡排序(Bubble Sort):
    冒泡排序是通过不断比较相邻的两个元素并交换位置,让较大(或较小)的元素逐渐往后(或往前)移动,直到所有元素都排好序。冒泡排序的时间复杂度是O(n^2),其中n是数组的长度。

    1. 从数组的第一个元素开始,比较它与下一个元素的大小。
    2. 如果当前元素大于下一个元素,则交换它们的位置。
    3. 继续比较下一个元素,重复步骤2,直到比较到倒数第二个元素。
    4. 完成一轮比较后,最大的元素已经被“冒泡”到数组的末尾。
    5. 重复步骤1-4,但是这次只需比较到倒数第三个元素,因为最后两个元素已经是有序的了。
    6. 重复执行步骤1-5,直到所有元素都被排序。
      public static 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]) {
                          // 交换arr[j]和arr[j+1]
                          int temp = arr[j];
                          arr[j] = arr[j + 1];
                          arr[j + 1] = temp;
                      }
                  }
              }
          }

  2. 插入排序(Insertion Sort):
    插入排序是将未排序的元素逐个插入已排序的序列中,通过不断比较和交换元素的位置,最终得到一个有序序列。插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。虽然插入排序的时间复杂度比较高,但是在实际应用中,当待排序序列基本有序时,插入排序的性能会比较好。

    1. 从第一个元素开始,该元素可以认为已经被排序。
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置。
    4. 重复步骤3,直到找到已排序的元素小于或等于新元素的位置。
    5. 将新元素插入到该位置后。
    6. 重复步骤2~5,直到所有元素都排序完毕。
      public static void insertionSort(int[] arr) {
              int n = arr.length;
              for (int i = 1; i < n; i++) {
                  int key = arr[i];
                  int j = i - 1;
      
                  while (j >= 0 && arr[j] > key) {
                      arr[j + 1] = arr[j];
                      j--;
                  }
                  arr[j + 1] = key;
              }
          }

  3. 选择排序(Selection Sort):
    选择排序是每次从未排序的元素中找到最小(或最大)的元素,将其放在已排序序列的末尾(或开头),直到所有元素都排好序。选择排序的时间复杂度为O(n^2),其中n为待排序数据的个数。它的优点是实现简单,不需要额外的存储空间,但是由于每次都要遍历剩余的未排序数据,因此效率较低。在实际应用中,选择排序一般适用于数据量较小的情况。

    1. 遍历待排序序列,从第一个元素开始,依次和后面的元素进行比较,找到最小(或最大)的元素。
    2. 将找到的最小(或最大)元素与第一个元素交换位置。
    3. 继续从第二个元素开始遍历,重复步骤1和步骤2,直到所有元素都排好序。
      public class SelectionSort {
          public static void selectionSort(int[] arr) {
              int n = arr.length;
              
              for (int i = 0; i < n-1; i++) {
                  int minIndex = i;
                  for (int j = i+1; j < n; j++) {
                      if (arr[j] < arr[minIndex]) {
                          minIndex = j;
                      }
                  }
                  
                  int temp = arr[minIndex];
                  arr[minIndex] = arr[i];
                  arr[i] = temp;
              }
          }
          
          public static void main(String[] args) {
              int[] arr = {64, 25, 12, 22, 11};
              selectionSort(arr);
              System.out.println("排序后的数组:");
              for (int num : arr) {
                  System.out.print(num + " ");
              }
          }
      }

  4. 快速排序(Quick Sort):
    快速排序是通过选择一个基准元素,将序列分割成左右两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素,然后分别对左右两部分进行递归排序。快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn)。它是一种原地排序算法,不需要额外的空间。

    1. 选择一个元素作为基准(pivot)。可以选择数组的第一个元素、最后一个元素或者随机选择一个元素作为基准。

    2. 将数组分为两部分,左边部分包含比基准小的元素,右边部分包含比基准大的元素。

    3. 对左右两部分分别进行递归排序。

    4. 合并左右两部分,即将左边部分的元素、基准元素、右边部分的元素按照顺序组合成一个有序数组。

      public class QuickSort {
          public void quickSort(int[] arr, int low, int high) {
              if (low < high) {
                  int pivotIndex = partition(arr, low, high);
                  quickSort(arr, low, pivotIndex - 1);
                  quickSort(arr, pivotIndex + 1, high);
              }
          }
      
          private int partition(int[] arr, int low, int high) {
              int pivot = arr[high];
              int i = low - 1;
              for (int j = low; j < high; j++) {
                  if (arr[j] <= pivot) {
                      i++;
                      swap(arr, i, j);
                  }
              }
              swap(arr, i + 1, high);
              return i + 1;
          }
      
          private void swap(int[] arr, int i, int j) {
              int temp = arr[i];
              arr[i] = arr[j];
              arr[j] = temp;
          }
      }

  5. 归并排序(Merge Sort):
    归并排序是将序列不断分割成两部分,分别对左右两部分进行递归排序,然后将排好序的左右两部分合并成一个有序序列。归并排序的时间复杂度为O(nlogn),其中n为待排序数组的长度。它是一种稳定的排序算法,适用于各种规模的数据集。但是归并排序需要额外的空间来存储临时数组,空间复杂度为O(n)。

    具体的归并排序算法如下:
    1. 将待排序的数组分割成两个子数组,直到每个子数组只有一个元素。
    2. 递归地对每个子数组进行归并排序。
    3. 将两个有序的子数组合并成一个有序的数组。       

        合并两个有序的子数组的过程如下:

  1.  创建一个临时数组,用于存放合并后的结果。
  2. 定义两个指针,分别指向两个子数组的起始位置。
  3. 比较两个指针指向的元素,将较小的元素放入临时数组中,并将对应指针向后移动一位。
  4. 重复步骤3,直到其中一个子数组的元素全部放入临时数组中。
  5. 将另一个子数组剩余的元素放入临时数组中。
  6. 将临时数组中的元素拷贝回原始数组中。
    public class MergeSort {
        public static void mergeSort(int[] arr) {
            if (arr == null || arr.length <= 1) {
                return;
            }
            
            int[] temp = new int[arr.length];
            mergeSort(arr, 0, arr.length - 1, temp);
        }
        
        private static void mergeSort(int[] arr, int start, int end, int[] temp) {
            if (start >= end) {
                return;
            }
            
            int mid = start + (end - start) / 2;
            mergeSort(arr, start, mid, temp); // 对左半部分进行归并排序
            mergeSort(arr, mid + 1, end, temp); // 对右半部分进行归并排序
            merge(arr, start, mid, end, temp); // 合并左右两个有序数组
        }
        
        private static void merge(int[] arr, int start, int mid, int end, int[] temp) {
            int left = start;
            int right = mid + 1;
            int index = start;
            
            while (left <= mid && right <= end) {
                if (arr[left] <= arr[right]) {
                    temp[index++] = arr[left++];
                } else {
                    temp[index++] = arr[right++];
                }
            }
            
            while (left <= mid) {
                temp[index++] = arr[left++];
            }
            
            while (right <= end) {
                temp[index++] = arr[right++];
            }
            
            for (int i = start; i <= end; i++) {
                arr[i] = temp[i];
            }
        }
        
        public static void main(String[] args) {
            int[] arr = {4, 2, 7, 1, 5, 9};
            mergeSort(arr);
            
            for (int num : arr) {
                System.out.print(num + " ");
            }
        }
    }

以上是对常见排序算法的简单介绍,实际上每种算法都有不同的实现方式和优化方法,可以根据具体问题和数据特点选择合适的算法。

标签:arr,掌握,int,复杂度,元素,算法,数组,经典,排序
From: https://blog.csdn.net/Maxianghua95/article/details/136647485

相关文章

  • 数据库基础--Redis知识体系(掌握Redis,看完这篇文章就够了!)
    1.Redis数据库Redis是一个开源的高性能键值存储数据库,类似字典。通常用作缓存、消息队列和数据存储等用途。mysql,mongodb都是以文件形式存储在磁盘上的,redis数据存在内存中,操作内存的速度远远高于磁盘,并且redis数据最终也可以存储在磁盘上。Redis支持多种数据结构,包括字符串......
  • 【算法训练营】最长公共子序列,倒水问题,奶牛吃草(Python实现)
    最长公共子序列时间限制:1sec空间限制:256MB问题描述给定两个1到n的排列A,B(即长度为n的序列,其中[1,n]之间的所有数都出现了恰好一次)。求它们的最长公共子序列长度。输入格式第一行一个整数n,意义见题目描述。第二行n个用空格隔开的正整数A[1],…,......
  • 【算法训练营】邓老师书,子序列,前缀(python实现)
    邓老师数时间限制:1sec空间限制:256MB问题描述众所周知,大于1的自然数中,除了1与其本身外不再有其他因数的数称作质数(素数)。对于大于1的不是质数的自然数,我们又称作合数。参加了邓老师算法训练营的小Z突发奇想,定义了新的数:所有合数中,除了1与其本身外,其他因......
  • 2024基于协同过滤算法springboot微信订餐小程序项目
    项目介绍基于springboot开发的订餐小程序,用户在微信小程序里面进行注册登录,点餐,收藏,评论等,管理员在后台网页端进行对菜品,分类,订单,用户,角色,评论等进行管理,小程序界面通过协同过滤算法给用户推荐菜品技术栈后端:springboot+JPA+Mysql8+redis+maven+idea前端:后台:HTML+JS+CSS......
  • C#判断素数的方法:试除法 vs 优化的试除法 vs 米勒-拉宾素数检测算法
    目录1.素数也就质数2.试除法3.优化的试除法_14.优化的试除法_25.优化的试除法_36.米勒-拉宾素数检测算法1.素数也叫质数        一个质数是一个大于1的自然数,只有两个正因数:1和它自身。这意味着如果一个数只有两个正因数,那么它就是一个质数。例如,2、3、5、7......
  • 查重算法
    论文查重这个作业属于哪个课程软件工程2024这个作业要求在哪里论文查重这个作业的目标学习如何作为软件工程师开发项目仓库地址:Nacyoooooo......
  • 力扣--深度优先算法/回溯算法47.全排列 Ⅱ
    思路分析:使用DFS算法进行全排列,递归地尝试每个可能的排列方式。使用path向量保存当前正在生成的排列,当其大小达到输入数组的大小时,将其加入结果集。使用numvisited向量标记每个数字是否已经被访问过,以确保每个数字在一个排列中只使用一次。在递归过程中,对于每个未访问的......
  • 代码随想录算法训练营day21 | leetcode 530. 二叉搜索树的最小绝对差、501. 二叉搜索
    目录题目链接:530.二叉搜索树的最小绝对差-简单题目链接:501.二叉搜索树中的众数-简单题目链接:236.二叉树的最近公共祖先-中等题目链接:530.二叉搜索树的最小绝对差-简单题目描述:给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,......
  • 深度学习4:感知器-三种激活函数及梯度下降算法
    文章目录1.感知器定义2.激活函数2.1常用的激活函数(1)三种激活函数的值域比较(2)三种函数对于定义域比较(3)PyTorch中的三种激活函数代码3求最优权重和偏置项(w,b)的方法3.1梯度下降算法(一元函数)实例3.2随机梯度下降算法(多元函数,单个样本)实例3.3批量梯度下降算法(......
  • Tarjan算法求SCC,缩点
    Tanjan算法可以在O(n+m)的时间内求出强连通分量,常数小,是个非常优秀的算法。算法实现过程:dfn[x]表示x的dfs生成树上的编号,代表着时间戳,low[x]表示从x结点出发,能够访问到最早的时间戳。<1>进入u时,盖上时间戳,结点入栈。<2>枚举该点的结点的时候,分为三种情况:(1)如果该点v没有访......