一. 冒泡排序(Bubble Sort)
算法描述(升序)
- 比较两个相邻的元素,如果前一个元素大于后一个元素,交换两元素位置
- 以第一步为基础,对相邻的两个元素进行对比和位置交换,这样每一次都将更大的元素“冒泡”到数组尾部(降序则是将更小的元素向后“冒泡”)
- 将数组中每个元素都进行操作,直到操作完成
-
冒泡排序的核心原理就是将对应的元素向数组的尾部移动,如升序是通过两元素之间的对比将更大的排在后面,两两元素进行位置交换,将每一次排序中最大的元素向数组尾部移动,直到数组每一个元素都被对比和交换之后,完成对数组元素的排序
-
演示:
-
JavaScript代码:
// 冒泡排序
function Bubble(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 1; j < arr.length - i; j++) {
if (arr[j - 1] > arr[j]) {
var temp = arr[j]
arr[j] = arr[j - 1]
arr[j - 1] = temp
}
}
}
}
var arr = [8, 3, 4, 2, 10, 1]
Bubble(arr)
console.log(arr) // [1, 2, 3, 4, 8, 10]
- Golang代码:
// 冒泡排序
func Bubble(arr []int) {
for i := 0; i < len(arr); i++ {
for j := 1; j < len(arr) -i; j++ {
if arr[j -1] > arr[j] {
arr[j], arr[j-1] = arr[j-1], arr[j]
}
}
}
}
func main() {
arr := [...]int{5, 3, 2, 7, 8}
Bubble(arr[:])
fmt.Println(arr) // [2 3 5 7 8]
}
二. 选择排序(Selection Sort)
算法描述(升序)
- 在操作数组中找到最小的元素,放在数组头部,此时整个数组分为有序部分和无序部分
- 在无序部分继续找其中最小的元素,并放在有序部分的尾部,直到完成排序
-
选择排序的 “选择” 在于要在操作的数组中找到对应的最大或最小的元素,同时数组在内部分为有序和无序两个部分,每次都在无序的部分中,找到对应的元素,放入到有序部分中
-
演示:
-
JavaScript代码:
function Selection(arr) {
var min
var temp
for (var i = 0; i < arr.length; i++) {
min = i
for (var j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j
}
}
temp = arr[i]
arr[i] = arr[min]
arr[min] = temp
}
}
var arr = [8, 3, 4, 2, 10, 9]
Selection(arr)
console.log(arr) // [2, 3, 4, 8, 9, 10 ]
- Golang代码:
// 选择排序
func Selection(arr []int) {
for i := 0; i < len(arr); i++ {
min := i
for j := i + 1; j < len(arr); j++ {
if arr[j] < arr[min] {
min = j
}
}
arr[i], arr[min] = arr[min], arr[i]
}
}
func main() {
arr := [...]int{8, 7, 5, 4, 3, 0, 15, 1}
Selection(arr[:])
fmt.Println(arr) // [0 1 3 4 5 7 8 15]
}
三. 快速排序(Quick Sort)
算法描述(升序)
- 在数组中选择一个元素,作为“基准”
- 所有比基准小的元素放在基准的前面,所有比基准大的元素放在基准的后面,如果数字相同则可以放在任意一边
- 余下利用递归操作对数组中的一个个“子列”进行“分区”
-
子列:操作数组中以基准为界限分出的数组部分
-
分区:对以基准进行区分的操作,称为分区操作,分区后当前基准就处于数组的中间位置
-
快速排序的基本思想就是通过一次次的分区,将数组分割为两个部分。其中一部分比另一部分小,则可分别对这两部分在进行分区,以递归的方式完成整个排序操作
-
演示:
-
JavaScript代码:
// 快速排序
function Quick(arr) {
if (arr.length <= 1) {
return arr
}
var pivotIndex = Math.floor(arr.length / 2)
var pivot = arr.splice(pivotIndex, 1)[0]
var left = []
var right = []
for (var i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return Quick(left).concat([pivot], Quick(right))
}
var arr = [10, 3, 4, 2, 9, 1]
console.log(Quick(arr)) // [ 1, 2, 3, 4, 9, 10 ]
- Golang代码:
func Quick(arr []int) []int {
if len(arr) < 2 {
return arr
}
pivot := arr[0]
var left []int
var right []int
for _, value := range arr[1:] {
if value < pivot {
left = append(left, value)
} else {
right = append(right, value)
}
}
var result []int
result = append(result, Quick(left)...)
result = append(result, pivot)
result = append(result, Quick(right)...)
return result
}
func main() {
arr := [...]int{5, 3, 2, 7, 8, 1}
fmt.Println(Quick(arr[:])) // [1 2 3 5 7 8]
}
四. 插入排序(Insertion Sort)
算法描述(升序)
- 默认数组的第一个元素是经过排序后的
- 取出下一个元素,我们可以称它为为flag
- 将flag与数组中已经排序的元素按从后向前的顺序比较,直到找到已排序部分的元素小于或者等于flag的位置;
- 不断重复,直到完成排序
-
插入排序的思想就是将数组中取出的当前元素与已排序元素进行比较,遇到更大的元素就向前继续比较,直到遇到比当前元素小的第一个元素,当前元素就放在其后面的位置,初始化认定数组第一个元素是已经排序好的
-
演示:
-
JavaScript代码:
function Insert(arr) {
var current
for (var i = 0; i < arr.length; i++) {
current = arr[i]
for (var j = i - 1; j > -1 && arr[j] > current; j--) {
arr[j + 1] = arr[j]
}
arr[j + 1] = current
}
return arr
}
var arr = [6, 3, 2, 7, 9, 10, 0]
Insert(arr)
console.log(arr) // [0, 2, 3, 6, 7, 9, 10]
- Golang代码
func Insert(arr []int) []int{
for i := 0; i < len(arr); i++ {
temp := arr[i]
for j := i -1;j >=0; j-- {
if temp < arr[j] {
arr[j+1], arr[j] = arr[j], arr[j+1]
} else {
break
}
}
}
return arr
}
func main() {
arr := [...]int{0, 6, 4, 7, 3, 2, 1, 10}
fmt.Println(Insert(arr[:])) // [0 1 2 3 4 6 7 10]
}