並べ替えを選択
選択ソートは、一般に、単純選択ソート(直接選択ソートとも呼ばれます)を指します。バブルソートのように要素を隣接して交換するのではなく、最小の要素を選択し、反復ごとに1回だけ交換する必要があります。交換の数はバブリングよりはるかに少ないですが、効率はバブリングソートと同じくらい悪いです。
選択ソートは、選択ソートアルゴリズムです。
ポーカーをプレイするときは、常に左から右にスキャンしてから、一番左のカードを左端に置き、次に2番目に小さいカードを2番目のカードから左から右にスキャンして、一番小さいカードに置きます。カードの右側で、これを繰り返します。選択の並べ替えは、ポーカーをプレイするときの並べ替えに特に似ています。
1.アルゴリズムの紹介
乱数列の束のような、があります5 9 1 6 8 14 6 49 25 4 6 3
。
最初の反復は、最初の数値から開始して、左から右にスキャンし、最小の数値1を見つけて、シーケンス内の最初の数値と位置を入れ替えます。
2番目の反復は、2番目の数値から開始して、左から右にスキャンし、2番目に小さい数値3を見つけて、シーケンス内の2番目の数値と位置を交換します。
3回目の反復では、3番目の数値から開始して左から右にスキャンし、3番目に小さい数値4を見つけて、シーケンス内の3番目の数値と位置を交換します。
N番目の反復:...
交換後の最終結果は次のとおり1 3 4 5 6 6 6 8 9 14 25 49
です。並べ替えられていることがわかります。
シーケンスをスキャンして最小数を見つけ、最初の数と交換し、最初の数を除外するたびに、この操作を2番目の数から繰り返します。この並べ替えは、単純選択並べ替えと呼ばれます。
簡単な例として、4要素シーケンスのソートを選択します4 2 9 1
。
[]表示排好序
起始: 4 2 9 1 未排序数列从左扫描最小的数是 1,与第一个元素 4 交换,交换 1,4
一轮: [1] 2 9 4 未排序数列从左扫描最小的数是 2,不需要交换
二轮: [1 2] 9 4 未排序数列从左扫描最小的数是 4,与第三个元素 9 交换,交换 4,9
三轮: [1 2 4] 9 未排序数列只有 1 个数,结束
结果: [1 2 4 9]
スキャンプロセスも比較プロセスであるため、バブリングソートと同じくらい多くの比較がありますが、交換回数は1ラウンドあたり1に減ります。ベストと最悪時間計算量が残っています:O(n^2)
。
選択の並べ替えは、配列などの不安定な並べ替えアルゴリズムです。[5 6 5 1]
最初の反復での最小数は1
であり、最初の要素と5
位置を交換します。その結果、数1
と数が5
位置を交換し、5
並べ替え後に2つの同じ数になります。場所が変更されました。
2.アルゴリズムの実装
package main
import "fmt"
func SelectSort(list []int) {
n := len(list)
// 进行 N-1 轮迭代
for i := 0; i < n-1; i++ {
// 每次从第 i 位开始,找到最小的元素
min := list[i] // 最小数
minIndex := i // 最小数的下标
for j := i + 1; j < n; j++ {
if list[j] < min {
// 如果找到的数比上次的还小,那么最小的数变为它
min = list[j]
minIndex = j
}
}
// 这一轮找到的最小数的下标不等于最开始的下标,交换元素
if i != minIndex {
list[i], list[minIndex] = list[minIndex], list[i]
}
}
}
func main() {
list := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6, 3}
SelectSort(list)
fmt.Println(list)
}
反復ごとに、このラウンドmin
の最小数:と最小数の添え字:を維持しminIndex
、スキャンを開始します。スキャン数がこの数より少ない場合は、最小と最小の添え字を置き換えます。交換は、その後交換すべきかどうかを決定しますlist[i], list[minIndex] = list[minIndex], list[i]
。
3、アルゴリズムの改善
上記のアルゴリズムは、特定の数から開始して最後までスキャンする必要があります。アルゴリズムを最適化して、複雑さを半分に減らすことができます。
各ラウンドで、最小数を見つけることに加えて、最大数も見つけて、前部要素と後部要素と別々に交換するので、次のようにサイクル数が半分になります。
package main
import "fmt"
func SelectGoodSort(list []int) {
n := len(list)
// 只需循环一半
for i := 0; i < n/2; i++ {
minIndex := i // 最小值下标
maxIndex := i // 最大值下标
// 在这一轮迭代中要找到最大值和最小值的下标
for j := i + 1; j < n-i; j++ {
// 找到最大值下标
if list[j] > list[maxIndex] {
maxIndex = j // 这一轮这个是大的,直接 continue
continue
}
// 找到最小值下标
if list[j] < list[minIndex] {
minIndex = j
}
}
if maxIndex == i && minIndex != n-i-1 {
// 如果最大值是开头的元素,而最小值不是最尾的元素
// 先将最大值和最尾的元素交换
list[n-i-1], list[maxIndex] = list[maxIndex], list[n-i-1]
// 然后最小的元素放在最开头
list[i], list[minIndex] = list[minIndex], list[i]
} else if maxIndex == i && minIndex == n-i-1 {
// 如果最大值在开头,最小值在结尾,直接交换
list[minIndex], list[maxIndex] = list[maxIndex], list[minIndex]
} else {
// 否则先将最小值放在开头,再将最大值放在结尾
list[i], list[minIndex] = list[minIndex], list[i]
list[n-i-1], list[maxIndex] = list[maxIndex], list[n-i-1]
}
}
}
func main() {
list := []int{5}
SelectGoodSort(list)
fmt.Println(list)
list1 := []int{5, 9}
SelectGoodSort(list1)
fmt.Println(list1)
list2 := []int{5, 9, 1}
SelectGoodSort(list2)
fmt.Println(list2)
list3 := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6, 3}
SelectGoodSort(list3)
fmt.Println(list3)
list4 := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6}
SelectGoodSort(list4)
fmt.Println(list4)
}
出力:
[5]
[5 9]
[1 5 9]
[1 3 4 5 6 6 6 8 9 14 25 49]
[1 4 5 6 6 6 8 9 14 25 49]
最適化されたソートはまだ非常に遅く、理解しやすいですが、エンジニアリングにはお勧めできません。
シリーズ記事エントリー
私は、スター陳思い、私が個人的に書かれているようこそ(Golangが達成)のデータ構造とアルゴリズムの記事で始まる、より親しみやすいGitBookを読むために。
- データ構造とアルゴリズム(Golang実装)(1)Golang-Prefaceの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(2)Golangパッケージ、変数、関数の簡単な紹介
- データ構造とアルゴリズム(Golang実装)(3)Golangフロー制御ステートメントの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(4)Golang構造とメソッドの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(5)Golangインターフェースの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(6)Golang並行性、コルーチン、チャネルの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(7)Golang標準ライブラリの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(8.1)基本的な知識-序文
- データ構造とアルゴリズム(Golang実装)(8.2)基本的な知識-分割と征服と再帰
- データ構造とアルゴリズム(Golang実装)(9)基本的な知識アルゴリズムの複雑さとプログレッシブシンボル
- データ構造とアルゴリズム(Golang実装)(10)基本知識-アルゴリズムの複雑さの主な方法
- データ構造とアルゴリズム(Golang実装)(11)一般的なデータ構造-序文
- データ構造とアルゴリズム(Golang実装)(12)一般的なデータ構造にリンクされたリスト
- データ構造とアルゴリズム(Golang実装)(13)一般的なデータ構造-可変長配列
- データ構造とアルゴリズム(Golang実装)(14)一般的なデータ構造-スタックとキュー
- データ構造とアルゴリズム(Golang実装)(15)一般的なデータ構造-リスト
- データ構造とアルゴリズム(Golang実装)(16)一般的なデータ構造-辞書
- データ構造とアルゴリズム(Golang実装)(17)一般的なデータ構造ツリー
- データ構造とアルゴリズム(Golang実装)(18)ソートアルゴリズム-序文
- データ構造とアルゴリズム(Golang実装)(19)ソートアルゴリズム-バブルソート
- データ構造とアルゴリズム(Golang実装)(20)ソートアルゴリズム選択ソート
- データ構造とアルゴリズム(Golang実装)(21)ソートアルゴリズム挿入ソート
- データ構造とアルゴリズム(Golang実装)(22)ソートアルゴリズム-ヒルソート
- データ構造とアルゴリズム(Golang実装)(23)ソートアルゴリズム-マージソート
- データ構造とアルゴリズム(Golang実装)(24)ソートアルゴリズム-優先度キューとヒープソート
- データ構造とアルゴリズム(Golang実装)(25)ソートアルゴリズム-迅速なソート
- データ構造とアルゴリズム(Golang実装)(26)ルックアップアルゴリズム-ハッシュテーブル
- データ構造とアルゴリズム(Golang実装)(27)検索アルゴリズム-バイナリ検索ツリー
- データ構造とアルゴリズム(Golang実装)(28)検索アルゴリズム-AVLツリー
- データ構造とアルゴリズム(Golang実装)(29)検索アルゴリズム-2-3ツリーと左寄りの赤黒ツリー
- データ構造とアルゴリズム(Golangによって実装)(30)検索アルゴリズム-2-3-4ツリーと通常の赤黒ツリー