前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >只知道冒泡排序?来看看这些排序算法

只知道冒泡排序?来看看这些排序算法

作者头像
Lvshen
发布于 2022-05-05 08:20:30
发布于 2022-05-05 08:20:30
16500
代码可运行
举报
运行总次数:0
代码可运行

那些年我们面试时经常会被问到排序算法,还有被要求现场手写排序算法。这篇文章我们来介绍下程序员遇到过的排序算法。

插入排序

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static int[] insertionSort(int[] array) {
   if (array.length == 0) {
      return array;
   }
   int current;
   for (int i = 0; i < array.length - 1; i++) {
      current = array[i + 1];
      int preIndex = i;
      while (preIndex >= 0 && current < array[preIndex]) {
         array[preIndex + 1] = array[preIndex];
         preIndex--;
      }
      array[preIndex + 1] = current;
   }
   return array;
}

冒泡排序

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 重复步骤1~3,直到排序完成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static int[] bubbleSort(int[] array) {
   if (array.length == 0) {
      return array;
   }
   for (int i = 0; i < array.length; i++) {
      for (int j = 0; j < array.length - 1 - i; j++) {
         if (array[j + 1] < array[j]) {
            int temp = array[j + 1];
            array[j + 1] = array[j];
            array[j] = temp;
         }
      }
   }
   return array;
}

选择排序(性能最稳定的排序算法之一)

  • 初始状态:无序区为R[1..n],有序区为空;
  • 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],
  • 将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
  • n-1趟结束,数组有序化了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static int[] selectionSort(int[] array) {
   if (array.length == 0) {
      return array;
   }
   for (int i = 0; i < array.length; i++) {
      int minIndex = i;
      for (int j = i; j < array.length; j++) {
         // 找到最小的数
         if (array[j] < array[minIndex]) {
            // 将最小数的索引保存
            minIndex = j;
         }
      }
      int temp = array[minIndex];
      array[minIndex] = array[i];
      array[i] = temp;
   }
   return array;
}

希尔排序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

public static int[] shellSort(int[] array) {
   int len = array.length;
   int temp, gap = len / 2;
   while (gap > 0) {
      for (int i = gap; i < len; i++) {
         temp = array[i];
         int preIndex = i - gap;
         while (preIndex >= 0 && array[preIndex] > temp) {
            array[preIndex + gap] = array[preIndex];
            preIndex -= gap;
         }
         array[preIndex + gap] = temp;
      }
      gap /= 2;
   }
   return array;
}

归并排序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制


public static int[] mergeSort(int[] array) {
   if (array.length < 2) {
      return array;
   }
   int mid = array.length / 2;
   int[] left = Arrays.copyOfRange(array, 0, mid);
   int[] right = Arrays.copyOfRange(array, mid, array.length);
   return merge(mergeSort(left), mergeSort(right));
}

快速排序方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制


public static int[] quickSort(int[] array, int start, int end) {
   if (array.length < 1 || start < 0 || end >= array.length || start > end) {
      return null;
   }
   int smallIndex = partition(array, start, end);
   if (smallIndex > start) {
      quickSort(array, start, smallIndex - 1);
   }
   if (smallIndex < end) {
      quickSort(array, smallIndex + 1, end);
   }
   return array;
}

private static int partition(int[] array, int start, int end) {
  int pivot = (int) (start + Math.random() * (end - start + 1));
  int smallIndex = start - 1;
  swap(array, pivot, end);
  for (int i = start; i <= end; i++) {
   if (array[i] <= array[end]) {
    smallIndex++;
    if (i > smallIndex) {
     swap(array, i, smallIndex);
    }
   }
  }
  return smallIndex;
}


private static void swap(int[] array, int i, int j) {
  int temp = array[i];
  array[i] = array[j];
  array[j] = temp;
}

桶排序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BucketSort {

   @Test
    public void test1(){
        int[] t = {5 ,3 ,5 ,2 ,8};
        bucketSort(t);
    }

   private void bucketSort(int[] t) {
      int a[] = new int[11];
      for (int i = 0; i < a.length; i++) {
         a[i] = 0;
      }

      for (int i = 0; i < t.length; i++) {
         int index = t[i];
         if (a[index] != 0) {
            a[index]++;
         } else {
            a[index] = 1;
         }
      }

      for (int i = 0; i < a.length; i++) {
         if (a[i] == 0) {
            continue;
         }
         for (int j = 0; j < a[i]; j++) {
            System.out.println(i);
         }
      }

   }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Lvshen的技术小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
什么是守护进程?
在了解守护进程之前,需要先知道什么是什么是终端?什么是作业?什么是进程组?什么是会话?
全栈程序员站长
2022/09/07
1.1K0
Nginx(4):守护进程,一份nginx实现,一份我的实现,看着拿呗
nginx的源码是比muduo要复杂些哈,muduo跟我以前写过的服务端项目有很多共通之处,就相当于是剥离了业务代码的网络层框架,所以看起来也比较亲切。这个nginx就感觉稍微有点陌生哈。
看、未来
2021/10/09
1.2K0
Linux守护进程
守护进程在 Linux 系统中极为重要,它们是许多服务器的核心组成部分,例如 Internet 服务器 inetd 和 Web 服务器 httpd。这些进程不仅负责提供网络服务,还执行各种系统任务,例如作业调度进程 crond。
不脱发的程序猿
2024/11/26
1790
Linux守护进程
Linux守护进程的编程实现
守护进程(Daemon)是执行在后台的一种特殊进程。它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种非常实用的进程。Linux的大多数server就是用守护进程实现的。比方,Internetserverinetd,Webserverhttpd等。同一时候,守护进程完毕很多系统任务。比方,作业规划进程crond,打印进程lpd等。 守护进程的编程本身并不复杂,复杂的是各种版本号的Unix的实现机制不尽同样,造成不同Unix环境下守护进程的编程规则并不一致。这须要读者注意,照搬某些书上的规则(特别是BSD4.3和低版本号的System V)到Linux会出现错误的。以下将全面介绍Linux下守护进程的编程要点并给出具体实例。 一. 守护进程及其特性 守护进程最重要的特性是后台执行。在这一点上DOS下的常驻内存程序TSR与之类似。其次,守护进程必须与其执行前的环境隔离开来。这些环境包含未关闭的文件描写叙述符,控制终端,会话和进程组,工作文件夹以及文件创建掩模等。这些环境一般是守护进程从执行它的父进程(特别是shell)中继承下来的。最后,守护进程的启动方式有其特殊之处。它能够在Linux系统启动时从启动脚本/etc/rc.d中启动,能够由作业规划进程crond启动,还能够由用户终端(一般是shell)执行。 总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么差别。因此,编写守护进程实际上是把一个普通进程依照上述的守护进程的特性改造成为守护进程。假设读者对进程有比較深入的认识就更easy理解和编程了。 二. 守护进程的编程要点 前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则事实上都一样,差别在于具体的实现细节不同。这个原则就是要满足守护进程的特性。同一时候,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点例如以下; 1. 在后台执行。 为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 if(pid=fork()) exit(0);//是父进程,结束父进程,子进程继续 2. 脱离控制终端,登录会话和进程组 有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话能够包含多个进程组。这些进程组共享一个控制终端。这个控制终端一般是创建进程的登录终端。 控制终端,登录会话和进程组一般是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: setsid(); 说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。因为会话过程对控制终端的独占性,进程同一时候与控制终端脱离。 3. 禁止进程又一次打开控制终端 如今,进程已经成为无终端的会话组长。但它能够又一次申请打开一个控制终端。能够通过使进程不再成为会话组长来禁止进程又一次打开控制终端:
全栈程序员站长
2022/07/14
2.4K0
守护进程
在Linux中,session(会话)通常指的是与用户交互的一个环境,它是系统中与某个用户交互的一系列活动的集合。会话在Linux系统中有多种用途,下面是几种常见的会话类型及其相关概念:
ljw695
2025/01/03
830
守护进程
13(守护进程)
守护进程是一种纯粹的后台进程,与运行前环境完全隔离,包括未关闭的文件描述符、控制终端、会话、进程组、工作目录以及文件创建掩码等 很多守护进程是父进程 fork 产生,所以会继承所有的父进程地址空间中的环境,所以必须在守护进程诞生之初,断绝这些相关环境,当然,守护进程也可以在 linux 系统启动时从启动脚本 /etc/rc.d 中启动,也可以由 crontab 启动 事实上,守护进程与普通进程的编写并没有特别大的区别
提莫队长
2019/02/21
8030
linux系统编程之进程(五):终端、作业控制与守护进程
该文介绍了如何在Linux系统中通过fork函数创建守护进程,并给出了具体的示例代码。同时,文章还介绍了守护进程的一些常见用途,如保证程序在后台运行、处理控制台输入输出等。
s1mba
2018/01/03
2.7K0
linux系统编程之进程(五):终端、作业控制与守护进程
Python守护进程daemon实现
守护进程是系统中生存期较长的一种进程,常常在系统引导装入时启动,在系统关闭时终止,没有控制终端,在后台运行。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。 在这里,我们在Linux2.6内核的centos中,ps -ef |awk '{print $1"\t "$2"\t "$3"\t  "$8}'看到:PPID=0的进程有两个,分别是PID=1的/sbin/init进程和PID=2的[kthreadd]进程。
py3study
2020/01/07
7.7K0
linux守护进程
这是创建守护进程的第一步。由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成程序已经运行完毕的假象。之后的所有工作都在子进程中完成,而用户在Shell终端里则可以执行其他命令,从而在形式上做到了与控制终端的脱离,在后台工作。
cpp加油站
2021/04/16
3.1K0
【计算机网络】日志与守护进程
一般使用cout进行打印,但是cout打印是不规范的 实际上 是采用日志进行打印的
lovevivi
2023/11/17
1830
【计算机网络】日志与守护进程
【Linux网络编程】:守护进程,前台进程,后台进程
●无控制终端:脱离控制终端,避免收到终端的干扰,它是和客户端进行交流的。和Xshell终端摆脱了联系。
用户11396661
2025/02/04
1050
【Linux网络编程】:守护进程,前台进程,后台进程
PHP 编写守护进程
PHP 创建守护进程 进程根据状态可以分为三种进程,守护进程,僵尸进程,孤儿进程。今天我们着重来分析下守护进程。 守护进程 简介 守护进程 (daemon) 是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。 创建步骤 创建子进程,终止父进程 由于守护进程是脱离控制终端的,因此首先创建子进程,终止父进程,使得程序在 shell 终端里造成一个已经运行完毕的假象。之后所有的工作都在子进程中完成,而
ITer.996
2019/08/28
1.7K0
守护进程
我们知道linux有许多自带的守护进程,比如syslogd、crond、sendmail等。那用户或开发者自己编写的程序为什么也需要成为守护进程呢?
Stare
2019/03/04
2.8K0
守护进程
Linux内核编程--进程组和守护进程
进程组:进程组是多个进程的集合, 接收同一个终端的各类信号信息。进程调用setpgid(pid, pgid)可以加入一个现有的进程组或者创建一个新的进程组。
Coder-ZZ
2022/05/09
3K0
Linux内核编程--进程组和守护进程
Linux守护进程
进程组,也叫做作业。BSD于1980年前后向Unix中增加的一个新特性,代表一个或者多个进程的集合,每个进程都属于一个进程组。操作系统设计进程组的概念主要就是为了简化对多个进程的管理。
mindtechnist
2024/08/08
1970
Linux守护进程
守护进程Xinted和日志记录Syslogd
调用fork函数创建子进程后,使父进程立即退出。这样,产生的子进程将变成孤儿进程,并被init进程接管,同时,所产生的新进程将变为在后台运行。
星哥玩云
2022/07/04
8930
进程组、会话、控制终端概念,如何创建守护进程?
守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程。周期性的执行某种任务或等待处理某些发生的事件。
睡魔的谎言
2020/11/25
1.5K0
守护进程(Daemon)
守护进程(Daemon)一般是为了保护我们的程序/服务的正常运行,当程序被关闭、异常退出等时再次启动程序/恢复服务。 例如 http 服务的守护进程叫 httpd,mysql 服务的守护进程叫 mysqld。
饶文津
2020/05/31
7.7K1
守护进程「建议收藏」
在UNIX系统中, 用户通过终端登录系统后得到一个Shell进程, 这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中, 控制终端是保存在PCB中的信息, 而fork会复制PCB中的信息, 因此由Shell进程启动的其它进程的控制终端也是这个终端. 默认情况下(没有重定向), 每个进程的标准输入, 标准输出和标准错误输出都指向控制终端, 进程从标准输入读也就是读用户的键盘输入, 进程往标准输出或标准错误输出写也就是输出到显示器上. 信号中还讲过, 在控制终端输入一些特殊的控制键可以给前台进程发信号, 例如Ctrl-C表示SIGINT,Ctrl-\表示SIGQUIT。
全栈程序员站长
2022/09/16
6000
python 守护进程(daemon)
通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端盒shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很容易的查看到,在这个shell环境下一开始执行的程序都是shell进程的子进程,自然会受到shell进程的影响,在程序里fork子进程后,父进程退出,对于shell进程来说,这个父进程就算执行完毕,而产生的子进程会被init进程接管,从而也就脱离了终端控制。
py3study
2020/01/10
1.1K0
相关推荐
什么是守护进程?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验