import java.io.PrintWriter
import com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner
import scala.collection.mutable.ArrayBuffer
import scala.io.Source
import scala.util.Random
import scala.util.control.Breaks._
/**
* 排序算法
* 插入排序:直接插入排序
* 选择排序:堆排序
* 交换排序:冒泡排序
* 交换排序:快速排序
* 选择排序:直接选择排序
* 归并排序
* 计数排序
* 桶排序
* 基数排序
*/
object SortArithmetic {
def main(args: Array[String]): Unit = {
// val timeStart = System.currentTimeMillis()
//
// // 随机产生待排序数据,大量数据时才能看出区别
// val num = 100000
// val createData = new PrintWriter("D:\\BaiduNetdiskDownload\\spark\\in")
// for (_ <- 1 to 30000000)
// createData.println(Random.nextInt(num))
// createData.close()
// val file = Source.fromFile("D:\\BaiduNetdiskDownload\\spark\\in")
// val preData = new ArrayBuffer[Int]
// for (line <- file.getLines())
// preData += line.toInt
// // 排序
// val sortedData = straightInsertionSort(preData)
// // 输出到本地
// val outData = new PrintWriter("D:\\BaiduNetdiskDownload\\spark\\out")
// for (i <- sortedData)
// outData.println(i)
// outData.close()
//
// // 统计时间
// val timeEnd = System.currentTimeMillis()
// println("straightInsertionSort runtime = " + (timeEnd - timeStart) / 1000.0 + " s")
val in = ArrayBuffer(7, 3, 1, 4, 2, 6, 5)
straightInsertionSort(in)
println(in)
}
/**
* 直接插入排序
* 遍历数组,调整当前元素到合适的位置,即已遍历部分有序
*/
def straightInsertionSort(inputData: ArrayBuffer[Int]): Unit = {
for (i <- 1 until inputData.length) {
val x = inputData(i)
var j = i - 1
while (j >= 0 && x < inputData(j)) {
inputData(j + 1) = inputData(j)
j = j - 1
}
inputData(j + 1) = x
}
}
/**
* 构造大顶堆
* @param inputData 无序数组
* @param m 最后一个非叶子节点的下标
* @param j 数组最后一个元素的下标
*/
def heapify(inputData: ArrayBuffer[Int], m: Int, j: Int): Unit = {
// 最后一个非叶子节点下标,值
var i = m
val x = inputData(i)
// 最后一个非叶子节点对应的叶子下标(后一个)
var k = 2 * i
breakable {
// 调用循环终止 break 方法
while (k <= j) {
if (k < j)
if (inputData(k) < inputData(k + 1)) k = k + 1
if (x >= inputData(k)) break
else {
inputData(i) = inputData(k)
i = k
k = 2 * i
}
}
}
inputData(i) = x
}
/**
* 堆排序
* 将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
* 将堆顶元素与末尾元素交换,将最大的元素沉到数组末端
* 重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素
* 反复执行调整 + 交换步骤,直到得到有序序列
* @return
*/
def heapSort(inputData: ArrayBuffer[Int]): ArrayBuffer[Int] = {
var i = inputData.length / 2
while (i >= 1) {
heapify(inputData, i - 1, inputData.length - 1)
i = i - 1
}
var j = inputData.length - 1
while (j > 0) {
val x = inputData(0)
inputData(0) = inputData(j)
inputData(j) = x
heapify(inputData, 0, j - 1)
j = j - 1
}
inputData
}
// 冒泡排序
def bubblingSort(inputData: ArrayBuffer[Int]): ArrayBuffer[Int] = {
for (j <- 0 to inputData.length - 3)
for (i <- 0 to inputData.length - 2 - j) {
if (inputData(i) > inputData(i + 1)) { //判断前一个元素是否大于后一个,如果大于,则交换
val temp = inputData(i + 1)
inputData(i + 1) = inputData(i)
inputData(i) = temp
}
}
inputData
}
// 快速排序
def qksort(inputData: ArrayBuffer[Int]): ArrayBuffer[Int] = {
def qsort1(inputData: ArrayBuffer[Int], left: Int, right: Int): Unit = {
if (left < right) {
var i = left
var j = right
val x = inputData(i)
while (i < j) {
while (i < j && inputData(j) > x) j = j - 1 /* 从右向左找第一个小于x的数 */
if (i < j) {
inputData(i) = inputData(j)
i = i + 1
}
while (i < j && inputData(i) < x) i = i + 1 /* 从左向右找第一个大于x的数 */
if (i < j) {
inputData(j) = inputData(i)
j = j - 1
}
}
inputData(i) = x
qsort1(inputData, left, i - 1) /* 递归调用 */
qsort1(inputData, i + 1, right)
}
}
qsort1(inputData, 0, inputData.length - 1)
inputData
}
// 选择排序
def SelectionSort(inputData: ArrayBuffer[Int]): ArrayBuffer[Int] = {
for (i <- 0 until inputData.length - 1) {
var index = i
var value = inputData(i)
for (j <- i + 1 until inputData.length) {
if (value > inputData(j)) {
index = j
value = inputData(j)
}
}
if (index != i) {
inputData(index) = inputData(i)
inputData(i) = value
}
}
inputData
}
// 归并排序
def merge(a: List[Int], b: List[Int]): List[Int] = (a, b) match {
case (Nil, _) => b
case (_, Nil) => a
case (x :: xs, y :: ys) =>
if (x <= y) x :: merge(xs, b)
else y :: merge(a, ys)
}
// InternalDescriptorAssigner
def mergeSort(lst: List[Int]): List[Int] = {
if (lst.length < 2) lst
else {
val (first, second) = lst.splitAt(lst.length / 2)
merge(mergeSort(first), mergeSort(second))
}
}
// 计数排序
def Countingsort(inputData: ArrayBuffer[Int], k: Int): Array[Int] = {
// k表示有所输入数字都介于0到k之间
val temp = new Array[Int](k)
// 临时存储区
val outdata = new Array[Int](inputData.length)
val len = temp.length
for (i <- 0 until len) {
// 初始化
temp(i) = 0
}
for (i <- inputData.indices) {
temp(inputData(i)) = temp(inputData(i)) + 1
}
for (i <- 1 until len) {
temp(i) = temp(i) + temp(i - 1)
}
// 把输入数组中的元素放在输出数组中对应的位置上
var n = inputData.length - 1
while (n >= 0) {
// 从后往前遍历
outdata(temp(inputData(n)) - 1) = inputData(n)
temp(inputData(n)) = temp(inputData(n)) - 1
n = n - 1
}
outdata
}
// 桶排序
def bucketsort(inputData: ArrayBuffer[Int], max: Int): ArrayBuffer[Int] = {
var buckets = new Array[Int](max)
for (i <- inputData.indices) //计数
buckets(inputData(i)) = buckets(inputData(i)) + 1
var j = 0
for (i <- 0 until max)
while (buckets(i) > 0) {
inputData(j) = i
j = j + 1
buckets(i) = buckets(i) - 1
}
buckets = null
inputData
}
/** 基数排序函数
* B表示要排序的数组
* d表示每一位数字的范围(这里是10进制数,有0~9一共10种情况)
*/
def RadixSort(inputData: ArrayBuffer[Int], d: Int): ArrayBuffer[Int] = {
//n用来表示当前排序的是第几位
var n = 1
//hasNum用来表示数组中是否有至少一个数字存在第n位
var hasNum = false
/** 二维数组temp用来保存当前排序的数字
* 第一维d表示一共有d个桶
* 第二维B.length表示每个桶最多可能存放B.length个数字
*/
val temp = Array.ofDim[Int](d, inputData.length)
val order = new Array[Int](d)
breakable {
while (true) {
// 判断是否所有元素均无比更高位,因为第一遍一定要先排序一次,所以有n!=1的判断
if (n != 1 && !hasNum) {
break
}
hasNum = false
// 遍历要排序的数组,将其存入temp数组中(按照第n位上的数字将数字放入桶中)
for (i <- inputData.indices) {
val x = inputData(i) / (n * 10)
if (x != 0) hasNum = true
val lsd = x % 10
temp(lsd)(order(lsd)) = inputData(i)
order(lsd) = order(lsd) + 1
}
// k用来将排序好的temp数组存入B数组(将桶中的数字倒出)
var k = 0
for (i <- 0 until d) {
if (order(i) != 0) {
var j = 0
while (j < order(i)) {
inputData(k) = temp(i)(j)
k = k + 1
j = j + 1
}
}
order(i) = 0
}
n = n + 1
}
}
inputData
}
}