目次
操作に従ってプログラムに注釈を付けます: (注釈を読むと、プログラムが各ステップでどのように動作するかがわかります)
単純な選択ソート
#include<iostream>
using namespace std;
#define MAXSIZE 20 //记录最大个数
typedef int KeyType; //关键字类型
typedef int InfoType;
//定义每个记录(数据元素)的结构
struct RecType
//Record Type:每条记录的类型
{
KeyType key; //关键字
InfoType otherinfo; //其他数据项
};
struct SqList
//顺序表(的)结构
{
RecType r[MAXSIZE + 1];
//类型为【记录类型】的数组
//r[0]一般做哨兵或缓冲区
int length; //顺序表长度
};
void SelectSort(SqList& L)
{
for (int i = 1; i <= L.length; i++)
{
int k = L.r[i].key;
for (int j = i; j <= L.length; j++)
{
if (L.r[j].key < k)
k = L.r[j].key;
}
if (k != L.r[i].key)
{
int temp = L.r[i].key;
L.r[i].key = k;
k = temp;
}
}
}
int main()
{
}
ヒープソート
ヒープ調整:
ダゲンドゥイ
void HeapAdjust(Elem R[], int s, int m) //Heap:堆
//二叉树空间范围:s-m,这里写的是大根堆
// s:smallest
// m:max
{
//调整R[s]的关键字,使R[s...m]重新成为一个大根堆
Elem rc = R[s];
for (int j = 2 * s; j <= m; j *= 2)
{
if (j < m && R[j] < R[j + 1])
j++; //j为关键字较大的数据元素下标
if (rc >= R[j])
break;
R[s] = R[j];
s = j; //记录位置
}
R[s] = rc; //插入
}
一番最初に、私たちはこのプログラムを見ましたが、まったく理解できませんでした。
私たちは、「彼はここで最後の要素をどうやって見つけたのでしょうか?」という質問さえしました。? ? なぜ見なかったのですか?
それでは、最初にひょうたんの絵に従って小さな根の山を作成/見つける方法を見つけてみましょう。
小さなルートヒープ
void HeapAdjust(Elem R[], int s, int m) //小根堆
{
Elem rc = R[s];
for (int j = 2 * s; j <= m; j *= 2)
{
if (j < m && R[j] > R[j + 1])
j++; //j为关键字较小的数据元素下标
if (rc <= R[j])
break;
R[s] = R[j];
s = j; //记录位置
}
R[s] = rc; //插入
}
それから私たちは長い間そのプログラムを黙ってたしなめ、そしてついにそれが何で書かれているかを理解しました。
ヒープ全体の調整の完全なプロセスは次のとおりです。
そしてここに(実際に私たちはここにいます):
PPT は実際に、ステップ 2 (図 2) からステップ 4 (図 4) までのプロセス全体のアルゴリズムを記述します。
tmd の代わりに、図 1 から始まるプロセス全体のアルゴリズムを使用します。
プログラムの開始時点で、デフォルトで図 1 から図 2 までの前工程が完了しており、事前に操作を手配してくれています。
顎関節症!
操作に従ってプログラムに注釈を付けます: (注釈を読むと、プログラムが各ステップでどのように動作するかがわかります)
小さな根の杭を例に挙げます: (大きな根の杭にも同じことが当てはまるので、ここでは繰り返しません)
void HeapAdjust(Elem R[], int s, int m) //小根堆
{
Elem rc = R[s];
//此时最后的元素已经被放到堆顶,rc记录最后一位元素
for (int j = 2 * s; j <= m; j *= 2)
//从第二层子树开始遍历
{
if (j < m && R[j] > R[j + 1])
j++;
//j:关键字较小的元素下标
if (rc <= R[j])
break;
//要最后一个元素比他小就算了,不然的话:
R[s] = R[j];
//j(较小)元素放上面去
s = j;
//下一轮for循环:
//从上一轮j的位置开始往下遍历
//以j的位置为根,向下遍历子树,不断把值小的元素移上去
}
R[s] = rc;
//最后,把最后的元素插入到最底部
// 注:
// 最后退出循环的时候s已经指向最底层了
// 而不出意外的话,最后的元素理论上也应该是堆里面最大的一个元素
}
ヒープの作成
#include<iostream>
using namespace std;
typedef int Elem;
void HeapAdjust(Elem R[], int s, int m) //小根堆
{
Elem rc = R[s];
//此时最后的元素已经被放到堆顶,rc记录最后一位元素
for (int j = 2 * s; j <= m; j *= 2)
//从第二层子树开始遍历
{
if (j < m && R[j] > R[j + 1])
j++;
//j:关键字较小的元素下标
if (rc <= R[j])
break;
//要最后一个元素比他小就算了,不然的话:
R[s] = R[j];
//j(较小)元素放上面去
s = j;
//下一轮for循环:
//从上一轮j的位置开始往下遍历
//以j的位置为根,向下遍历子树,不断把值小的元素移上去
}
R[s] = rc;
//最后,把最后的元素插入到最底部
// 注:
// 最后退出循环的时候s已经指向最底层了
// 而不出意外的话,最后的元素理论上也应该是堆里面最大的一个元素
}
void Swap(int a, int b)
{
int temp=b;
b = a;
a = temp;
}
void HeapSort(Elem R[],int n)
{
int i;
for (i = n / 2; i >= 1; i--)
HeapAdjust(R, i, n);
// 我们默认R[]数据无序
// 先把R[]中的无序数据都排一遍顺序
// 相当于我们先构造出一个合格的图1
for (i = n; i > 1; i--)
{
cout << R[1] << endl;//逐个输出元素
Swap(R[1], R[i]);
//互换最后一个元素和根
//相当于执行图1加工到图2的过程
HeapAdjust(R, 1, i - 1);
//面向剩下的元素重新建堆
}
}
int main()
{
}
質問:
最後の要素とルートの交換がプログラムの結果に影響するかどうかについては、心配する必要はありません。
ルートレット ヒープをソートすると、次のようになります。
最後の要素、つまり最大の要素は、二分木のサブツリー内でより大きな値を持つ側になければなりません。
そして、後続の走査ソートで変更するのは、バイナリ ツリー サブツリーの小さい値を持つ側であるため、影響はありません。
ダゲンドゥイも同様なので繰り返さない