Data Structure and Algorithm Fundamentals (Wang Zhuo) (37): Selection Sort (Simple Selection, Heap Sort)

Table of contents

simple selection sort

heap sort

Heap adjustments:

Dagendui

small root heap

The complete process of the whole heap adjustment is as follows:

 Annotate the program according to the operation: (After reading the annotation, you will know how the program operates at each step)

heap creation

question


simple selection sort

#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()
{

}


heap sort


Heap adjustments:

Dagendui

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;  //插入
}

At the very beginning (at the very beginning), we looked at this program, it was completely incomprehensible, wow

We even asked the question: how did he find the last element here? ? ? Why didn't I see it?

So let's first create/find a way to make a small root pile according to the gourd painting:

small root heap

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;  //插入
}

Then we kowtowed silently at the program for a long time, and finally figured out what it was written in:

The complete process of the whole heap adjustment is as follows:

And here (actually here we are):

PPT actually writes the algorithm of the whole process from step 2 (Figure 2) to step 4 (Figure 4)

Instead of tmd the algorithm for the whole process starting from Figure 1

At the beginning of the program, he has already completed the previous process operations from Figure 1 to Figure 2 by default, and has arranged operations for us in advance.

TMD!

 Annotate the program according to the operation: (After reading the annotation, you will know how the program operates at each step)

Take the small root pile as an example: (The same is true for the big root pile, so I won’t repeat it here)

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已经指向最底层了
    // 而不出意外的话,最后的元素理论上也应该是堆里面最大的一个元素
}

heap creation

#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()
{

}

​​​​​​​

question:

 As for whether the exchange of the last element and the root will affect the result of the program, we don't have to worry about this:

When we sort the rootlet heap:

The last element, that is, the largest element, must be on the side with a larger value in the binary tree subtree

And what we change in subsequent traversal sorting is the side with the smaller value of the binary tree subtree, so it must have no effect

The same is true for Dagendui, so I won’t repeat it

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/130461642
Recommended