• 排序


    排序的介绍

    排序是将一组数据,依指定的顺序进行排列的过程, 常见的排序:

    1. 冒泡排序
    2. 选择排序
    3. 插入排序
    4. 快速排序
    5. 归并排序

     

    冒泡排序

    冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较

    相邻元素的排序码,若发现逆序则交换,使排序码较小的元素逐渐从后部移向前部(从下标较大的单元移向下

    标较小的单元),就象水底下的气泡一样逐渐向上冒。

     

    因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下

    来没有进行过交换,就说明序列有序,因此要在排序过程中设置

    一个标志flag判断元素是否进行过交换。从而减少不必要的比较。

     

    冒泡排序,前面的老师,已经讲过了。

     

    • 冒泡排序的代码:

    package com.atguigu.temp.sort

    import java.text.SimpleDateFormat

    import java.util.Date

    object BubbleSort {

    def main(args: Array[String]): Unit = {

    //数组

    //val arr = Array(3, 9, -1, 10, 20)

    //创建一个80000个随机数据的数组

    val random = new util.Random()

    val arr = new Array[Int](80000)

    for (i <- 0 until 80000) {

    arr(i) = random.nextInt(8000000)

    }

    println("排序前")

    val now: Date = new Date()

    val dateFormat: SimpleDateFormat =

    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    val date = dateFormat.format(now)

    println("排序前时间=" + date) //输出时间

     

    println(arr.mkString(" "))

    println("排序后")

    bubbleSort(arr)

    println(arr.mkString(" "))

    val now2: Date = new Date()

    val date2 = dateFormat.format(now2)

    println("排序后时间=" + date2) //输出时间

    }

    def bubbleSort(arr: Array[Int]): Unit = {

     

    for (i <- 0 until arr.length - 1) {

    for (j <- 0 until arr.length - 1 - i) {

    if (arr(j) > arr(j + 1)) {

    val temp = arr(j)

    arr(j) = arr(j + 1)

    arr(j + 1) = temp

    }

    }

    }

    }

    }

     

     

    选择排序基本介绍

    选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,经过和其他元素重整,再依规定()交换位置后达到排序的目的。

     

    选择排序思想:

    选择排序(select sorting)也是一种简单的排序方法。它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,第三次从R[2]~R[n-1]中选取最小值,与R[2]交换,…,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,…, n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。

     

    选择排序思路分析图:

    选择排序的代码实现

    package com.atguigu.chapter18.sort

     

    import java.text.SimpleDateFormat

    import java.util.Date

     

    object SelectSort {

    def main(args: Array[String]): Unit = {

    //var arr = Array(101, 34, 119, 1)

     

    val random = new util.Random()

    val arr = new Array[Int](80000)

    for (i <- 0 until 80000) { //循环的生成随机数

    arr(i) = random.nextInt(8000000)

    }

    println("排序前")

    val now: Date = new Date()

    val dateFormat: SimpleDateFormat =

    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    val date = dateFormat.format(now)

    println("排序前时间=" + date) //输出时间

     

    //我们发现规律,调用选择排序

    selectSort(arr)

     

    println("排序后")

    //println(arr.mkString(" "))

    val now2: Date = new Date()

    val date2 = dateFormat.format(now2)

    println("排序后时间=" + date2) //输出时间

     

     

     

     

    //我们看一下排序的一个演变过程

    //1轮排序 (101, 34, 119, 1) => (1, 34, 119, 101)

     

    /*

     

    var min = arr(0)

    var minIndex = 0

    //遍历

    for (j <- (0 + 1) until arr.length) {

    if (min > arr(j)) { // 说明min不是真的最小值

    min = arr(j) // 重置min

    minIndex = j // 重置minIndex

    }

    }

    //判断是否需要交换

    if (minIndex != 0) {

    arr(minIndex) = arr(0)

    arr(0) = min

    }

     

    println("1轮结束")

    println(arr.mkString(" "))

     

    //2轮排序 (1, 34, 119, 101) => (1, 34, 119, 101)

     

    min = arr(1)

    minIndex = 1

    //遍历

    for (j <- (1 + 1) until arr.length) {

    if (min > arr(j)) { // 说明min不是真的最小值

    min = arr(j) // 重置min

    minIndex = j // 重置minIndex

    }

    }

    //判断是否需要交换

    if (minIndex != 1) {

    arr(minIndex) = arr(1)

    arr(1) = min

    }

     

    println("2轮结束")

    println(arr.mkString(" "))

     

     

    //3轮排序 (1, 34, 119, 101) => (1, 34, 101, 119)

     

    min = arr(2)

    minIndex = 2

    //遍历

    for (j <- (2 + 1) until arr.length) {

    if (min > arr(j)) { // 说明min不是真的最小值

    min = arr(j) // 重置min

    minIndex = j // 重置minIndex

    }

    }

    //判断是否需要交换

    if (minIndex != 2) {

    arr(minIndex) = arr(2)

    arr(2) = min

    }

     

    println("3轮结束")

    println(arr.mkString(" "))

    */

     

    }

     

    def selectSort(arr:Array[Int]): Unit = {

     

    for (i <- 0 until arr.length -1) {

    var min = arr(i)

    var minIndex = i

    //遍历

    for (j <- (i + 1) until arr.length) {

    if (min > arr(j)) { // 说明min不是真的最小值

    min = arr(j) // 重置min

    minIndex = j // 重置minIndex

    }

    }

    //判断是否需要交换

    if (minIndex != i) {

    arr(minIndex) = arr(i)

    arr(i) = min

    }

     

    // println(s"${i+1}轮结束")

    // println(arr.mkString(" "))

    }

    }

    }

     

     

    插入排序法介绍:

    插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。

     

    插入排序法思想:

    插入排序(Insertion Sorting)的基本思想是:n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

    插入排序法思路示意图

    插入排序的代码实现

    package com.atguigu.chapter18.sort

     

    import java.text.SimpleDateFormat

    import java.util.Date

     

    object InsertSort {

    def main(args: Array[String]): Unit = {

     

    //测试数组

    //val arr = Array(101, 34, 119, 1,-1, 45,900)

     

    val random = new util.Random()

    val arr = new Array[Int](80000)

    for (i <- 0 until 80000) { //循环的生成随机数

    arr(i) = random.nextInt(8000000)

    }

    println("排序前")

    val now: Date = new Date()

    val dateFormat: SimpleDateFormat =

    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    val date = dateFormat.format(now)

    println("排序前时间=" + date) //输出时间

     

    insertSort(arr) //调用插入排序

     

    println("插入排序后")

     

    val now2: Date = new Date()

    val date2 = dateFormat.format(now2)

    println("排序后时间=" + date2) //输出时间

    //println(arr.mkString(" "))

     

     

    //1轮插入排序

    //(101), 34, 119, 1 => (34,101),119,1

     

    // (101, 101) 119, 1

    /* var insertVal = arr(1)

    var insertIndex = 1 - 1 // 表示有序表的最后这个元素的下标

     

    //还没找到位置

    while (insertIndex >= 0 && insertVal < arr(insertIndex)) {

    arr(insertIndex+1) = arr(insertIndex)

    insertIndex -= 1

    }

    //退出while 说明插入的位置就找到了

    arr(insertIndex + 1) = insertVal

     

    println("1轮的结果是")

    println(arr.mkString(" "))

     

     

    //2

    insertVal = arr(2)

    insertIndex = 2 - 1 // 表示有序表的最后这个元素的下标

     

    //还没找到位置

    while (insertIndex >= 0 && insertVal < arr(insertIndex)) {

    arr(insertIndex+1) = arr(insertIndex)

    insertIndex -= 1

    }

    //退出while 说明插入的位置就找到了

    arr(insertIndex + 1) = insertVal

     

    println("2的结果是")

    println(arr.mkString(" "))

     

     

    //3

    insertVal = arr(3)

    insertIndex = 3 - 1 // 表示有序表的最后这个元素的下标

     

    //还没找到位置

    while (insertIndex >= 0 && insertVal < arr(insertIndex)) {

    arr(insertIndex+1) = arr(insertIndex)

    insertIndex -= 1

    }

    //退出while 说明插入的位置就找到了

    arr(insertIndex + 1) = insertVal

     

    println("3的结果是")

    println(arr.mkString(" "))*/

     

    }

     

    def insertSort(arr:Array[Int]): Unit ={

    //发现规律

    for (i <- 1 until arr.length) {

    var insertVal = arr(i)

    var insertIndex = i - 1 // 表示有序表的最后这个元素的下标

     

    //还没找到位置

    while (insertIndex >= 0 && insertVal < arr(insertIndex)) {

    arr(insertIndex+1) = arr(insertIndex)

    insertIndex -= 1

    }

    //退出while 说明插入的位置就找到了

    arr(insertIndex + 1) = insertVal

     

    // println(s"${i}轮的结果是")

    // println(arr.mkString(" "))

    }

    }

    }

     

    /*

    插入排序的思路:

    插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

     

    */

     

    快速排序法介绍:

    快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

     
    快速排序法示意图:

    1. 代码实现

    package com.atguigu.chapter18.sort

     

    import java.text.SimpleDateFormat

    import java.util.Date

     

    import util.control.Breaks._

     

    object QuickSort {

    def main(args: Array[String]): Unit = {

     

    //val arr = Array(-9,78,0,23,-567,70)

     

    val random = new util.Random()

    val arr = new Array[Int](80000000)

    for (i <- 0 until 80000000) { //循环的生成随机数

    arr(i) = random.nextInt(8000000)

    }

    println("排序前")

    val now: Date = new Date()

    val dateFormat: SimpleDateFormat =

    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    val date = dateFormat.format(now)

    println("排序前时间=" + date) //输出时间

     

    quickSort(0, arr.length -1, arr) // 调用快排

    println("排序后")

     

    val now2: Date = new Date()

    val date2 = dateFormat.format(now2)

    println("排序后时间=" + date2) //输出时间

    //println(arr.mkString(" ")) // ( 0 )// -567 -9 0 23 78 70

    }

     

    /*

    1. left: 指定从数组的左边的下标 0

    2. right : 指定从数组的右边的下标 length -1

    3. arr : 进行排序的数组

    */

    def quickSort(left: Int, right: Int, arr: Array[Int]): Unit = {

    var l = left // 左下标

    var r = right // 右下标

    var pivot = arr((left + right) / 2) // 以中间的值为基准进行分割

    var temp = 0

    breakable {

    // while 语句的作用就是把比 pivot 小的数放到左边, pivot大的数放到右边

    while (l < r) {

    while (arr(l) < pivot) { //从左边找一个比 pivot 大的值对应下标

    l += 1

    }

    while (arr(r) > pivot) { //从右边找一个比 pivot 小的值对应下标

    r -= 1

    }

    if (l >= r) { // 说明本次交换结束,退出本次while

    break()

    }

    var temp = arr(l) //交换

    arr(l) = arr(r)

    arr(r) = temp

    //处理后,如果发现arr(l) == pivot r - =1 , 提高效率

    if (arr(l) == pivot) {

    r -= 1

    }

    //

    if ((arr(r)) == pivot) {

    l += 1

    }

    }

    }

    if (l == r) { // 提高效率

    l += 1

    r -= 1

    }

     

    if (left < r) { //向左递归排序

    quickSort(left, r, arr)

    }

    if (right > l) {//向右递归排序

    quickSort(l, right, arr)

    }

    }

     

    }

     

     

    归并排序介绍:

    归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)

     

    归并排序思想示意图1-基本思想:

    归并排序思想示意图2-合并相邻有序子序列:

    再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8][1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤

    1. 归并排序的代码实现

    package com.atguigu.chapter18.sort

     

    import java.text.SimpleDateFormat

    import java.util.Date

     

    object MergeSort {

    def main(args: Array[String]): Unit = {

     

    //var arr = Array(-9, 78, 0, 23, -567, 70)

     

    val random = new util.Random()

    val arr = new Array[Int](80000000)

    for (i <- 0 until 80000000) { //循环的生成随机数

    arr(i) = random.nextInt(8000000)

    }

    println("排序前")

    val now: Date = new Date()

    val dateFormat: SimpleDateFormat =

    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    val date = dateFormat.format(now)

     

    val temp = new Array[Int](arr.length) //临时的数组

     

    println("排序前时间=" + date) //输出时间

     

    mergeSort(arr, 0, arr.length - 1, temp) //调用归并排序法

     

    println("归并排序后")

     

    val now2: Date = new Date()

    val date2 = dateFormat.format(now2)

    println("排序后时间=" + date2) //输出时间

     

    // println(arr.mkString(" "))

     

    }

     

    //是后一个归并排序

    /*

    1. arr :待排序的数组

    2. left: 最初的左边的下标 0

    3. right: 最初的右边下标 length - 1

    4. temp 就是临时数组 , 事先就开辟好的,大小和 arr 一样.

    */

    def mergeSort(arr: Array[Int], left: Int, right: Int, temp: Array[Int]): Unit = {

    if (left < right) { //如果 left < right 就可以继续分

    val mid = (left + right) / 2

    mergeSort(arr, left, mid, temp) // 递归将左边的数据做成有序列表

    mergeSort(arr, mid + 1, right, temp) //递归将右边的数据做成有序列表

    // merge 是合并的操作

    merge(arr, left, mid, right, temp)

    }

    }

     

    def merge(arr: Array[Int], left: Int, mid: Int, right: Int, temp: Array[Int]) {

    var i = left // i 就是左边指针[索引]

    var j = mid + 1 //j 就是右边的指针

    var t = 0 // t temp 数组的索引

    while (i <= mid && j <= right) {

    // 如果是当前的左边的有序列表的值小于当前的右边有序列表的值

    // 就把这个值拷贝到 temp数组

    if (arr(i) <= arr(j)) {

    temp(t) = arr(i)

    t += 1

    i += 1

    } else { // 如果是当前的右边的有序列表的值小于当前的左边有序列表的值,就把这个值拷贝到 temp数组

    temp(t) = arr(j)

    t += 1

    j += 1

    }

    }

    while (i <= mid) { //如果左边有序列表还有剩余数据,就依次拷贝到temp数组

    temp(t) = arr(i)

    t += 1

    i += 1

    }

    while (j <= right) { //如果右边有序列表还有剩余数据,就依次拷贝到temp数组

    temp(t) = arr(j)

    t += 1

    j += 1

    }

     

    // 下面代码是完成将本次的temp 的数据拷贝到arr

    t = 0

    var tempLeft = left

    while (tempLeft <= right) {

    arr(tempLeft) = temp(t)

    t += 1

    tempLeft += 1

    }

    }

     

     

    }

     

    课后思考题: {1,8, 10, 89, 1000, 10001234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.

    • 新版的代码如下

    package com.atguigu.chapter18.search

     

    import scala.collection.mutable.ArrayBuffer

    import util.control.Breaks._

     

    object BinarySearch {

    def main(args: Array[String]): Unit = {

     

    val arr = Array(1, 8, 10, 1000, 1000,1000, 1000, 1000, 1000,1000, 1000,1000, 1234)

    // val index = binarySearch(arr, 0, arr.length - 1, 1000)

    // if (index != -1) {

    // println("找到,下标为" + index)

    // } else {

    // println("没有找到")

    // }

     

    var resArr = binarySearch2(arr, 0, arr.length - 1, 1000)

    resArr = resArr.sortBy((x:Int) => x)

    if (resArr.length != 0) {

    for (index<-resArr) {

    println("找到的索引有" + index)

    }

    }else {

    println("没有找到")

    }

    }

     

    //二分查找的思路

    //1. 先找到中间值

    //2. 然后将中间值和查找值比较

    //2.1 相等,找出

    //2.2 中间值 > 查找值, 向左进行递归查找

    //2.3 中间值 < 查找值, 向右进行递归查找

    // ? 在什么情况下,表示找不到?

    //如果存在值,就返回对应的下标,否则返回-1

    def binarySearch(arr: Array[Int], l: Int, r: Int, findVal: Int): Int = {

     

    //找不到条件?

    if (l > r) {

    return -1

    }

     

    val midIndex = (l + r) / 2

    val midVal = arr(midIndex)

    if (midVal > findVal) {

    //向左进行递归查找

    binarySearch(arr, l, midIndex - 1, findVal)

    } else if (midVal < findVal) { //向右进行递归查找

    binarySearch(arr, midIndex + 1, r, findVal)

    } else {

    return midIndex

    }

     

    }

     

    /*

    课后思考题: {1,8, 10, 89, 1000, 10001234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.

    //分析

    1. 返回的结果是一个可变数组 ArrayBuffer

    2. 在找到结果时,向左边扫描,向右边扫描 [条件]

    3. 找到结果后,就加入到ArrayBuffer

    */

    def binarySearch2(arr: Array[Int], l: Int, r: Int,

    findVal: Int): ArrayBuffer[Int] = {

     

    //找不到条件?

    if (l > r) {

    return ArrayBuffer()

    }

     

    val midIndex = (l + r) / 2

    val midVal = arr(midIndex)

    if (midVal > findVal) {

    //向左进行递归查找

    binarySearch2(arr, l, midIndex - 1, findVal)

    } else if (midVal < findVal) { //向右进行递归查找

    binarySearch2(arr, midIndex + 1, r, findVal)

    } else {

    println("midIndex=" + midIndex)

    //定义一个可变数组

    val resArr = ArrayBuffer[Int]()

    //向左边扫描

    var temp = midIndex - 1

    breakable {

    while (true) {

    if (temp < 0 || arr(temp) != findVal) {

    break()

    }

    if (arr(temp) == findVal) {

    resArr.append(temp)

    }

    temp -= 1

    }

    }

    //将中间这个索引加入

    resArr.append(midIndex)

    //向右边扫描

    temp = midIndex + 1

    breakable {

    while (true) {

    if (temp > arr.length - 1 || arr(temp) != findVal) {

    break()

    }

    if (arr(temp) == findVal) {

    resArr.append(temp)

    }

    temp += 1

    }

    }

    return resArr

    }

     

    }

    }

     

  • 相关阅读:
    Delphi实战中讲解FormCreate,FormShow,FormActivate
    delphi Try except on e:Exception do
    Delphi处理数据网格DBGrid的编辑框 获取还没有提交到数据集的字段文本
    delphi dbgrid中如何自动生成序号
    DBDateTimePicker;
    Delphi控件开发浅入深出(八)
    delphi中日期类型TDateTime使用总结
    在DBGrid录数据时,如何判断光标位置是在数据的最左或最右,如果是最左或最右则在按左右光标键时光标跳到上一格或下一格,如果是在数据中
    请问如何按Enter键让DBGrid的光标向右移以及换行?(0分)
    tdbgrid中用enter仿真tab键盘_delphi教程
  • 原文地址:https://www.cnblogs.com/shuzhiwei/p/11210085.html
Copyright © 2020-2023  润新知