Data Structure and Algorithm Fundamentals (Wang Zhuo) (33): Binary Insertion Sort, Hill Sort

Table of contents

Binary Insertion Sort

 Project 1:

Problem: Missing operations to move elements before inserting them

Project 2: (final product, result)

Hill sort

 Project 1: (personal idea)

Standard answer: (PPT answer)

Explanation: (The logic sequence of the algorithm when the program is actually executed is actually different from what Mr. Wang Zhuo taught in the online class)

(1): Assignment stage

(2): The first round [first time] comparison

 (3): Comparison from the second round to the (d) round [first time]

(4): Comparison from the first round to the (d) round [the second and subsequent rounds]

Here comes the point:

As for how to adjust the different interval sizes d when comparing successively, the method given in the standard answer here is:

The benevolent answer:

localization


Binary Insertion Sort


Write the following program directly based on the actual example and the sketch: 

 Project 1:

void BinsertSort(SqList& L)
{
    int i ,low = 1, high = i - 1;
    for (i = 1; i < L.length; i++)
    {
        if (L.r[i].key < L.r[i - 1].key)
            L.r[0] = L.r[i];
        //if可以放到最高优先级
        for (int mid = (low + high) / 2; high > low; mid = (low + high) / 2)
        {
            if (L.r[0].key < L.r[mid].key)
                high = mid - 1;
            else //if (L.r[0].key > L.r[mid].key)
                low = mid + 1;
        }
        L.r[high + 1].key = L.r[0].key;
        //L.r[low - 1].key = L.r[0].key;
    }
}

binary insert;
binary: binary; based on only two numbers; binary; consisting of two parts;

Problem: Missing operations to move elements before inserting them


Project 2: (final product, result)

void BinsertSort(SqList& L)
//binary insert;
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int i;
    for (i = 1; i < L.length; i++)
        //i表示位序
    {
        if (L.r[i].key < L.r[i - 1].key)
            L.r[0] = L.r[i];
int low = 1, high = i - 1;
        for (int mid = (low + high) / 2; high > low; mid = (low + high) / 2)
        {
            if (L.r[0].key < L.r[mid].key)
                high = mid - 1;
            else //if (L.r[0].key > L.r[mid].key)
                low = mid + 1;
        }
        for (int j = i; j >= high + 1; j--)
            L.r[j + 1].key = L.r[j].key;

        L.r[high + 1].key = L.r[0].key;
        //L.r[low - 1].key = L.r[0].key;
    }
}

Hill sort

Write the following program directly based on the actual example and the sketch: 

 Project 1: (personal idea)

void ShellSort(SqList& L) 
{
    for (int i = 0; i <= L.length / 5; i++)
    {
        for (int i = 0; i <= L.length; i += 5)
        {
            每次都把数据存储到中序二叉树,再用中序遍历把这些元素全部都重新插回去
        }
        递归...
    }
}

Standard answer: (PPT answer)

void ShellInsert(SqList& L, int d)
//distance:每次一步往后跨多远(5,3,1...)
{
    int i, j;
    for (i = d + 1; i < L.length; i++) 
    {
        if (L.r[i].key < L.r[i - d].key) 
            //比较的诸多元素里,第二个元素大于第一个元素
        {
            L.r[0] = L.r[i];  
            for (j = i - d; //第一个元素
                j > 0 && (L.r[0].key < L.r[j].key);
                j -= d)
                L.r[j + d] = L.r[j];  //记录后移
            L.r[j + d] = L.r[0];  
        }
    }
}
void ShellSort(SqList& L, int dlta[], int t)
//t:循环总共趟数
{
    for (int k = 0; k < t; k++)
        ShellInsert(L, dlta[k]); 
    //dlta[k]:增量(5, 3, 1...)
}

Explanation: (The logic sequence of the algorithm when the program is actually executed is actually different from what Mr. Wang Zhuo taught in the online class)


(1): Assignment stage

The initial value of i is the second element of each comparison

Among the many elements compared, if the second element is greater than the first element: start the loop


(2): The first round [first time] comparison

The first operation of the first round of comparison only compares the two previously selected elements:


Compare the 1st and (d+1)th elements

  1. Put the second element into the sentinel
  2. The first element covers the second element
  3. Then transfer the second element from the sentinel to the position of the first element

Then: j-=d; => j<0


The first round of comparison is over

In fact, the complete sorting of this block is not over

However, due to the fact that Hill sorting deviates from the algorithm ideas taught by the teacher

Therefore, for: we divide the data into d parts, and perform a total of d rounds of sorting in the first round of the algorithm, it is paused and terminated here


Then ( after the first round of comparison ), the operation we performed was not as Mr. Wang said:

Go to the next block to filter out, the third and subsequent other elements for comparison and sorting

Instead, temporarily suspend the block algorithm operation and find the second element we stored inside the data:


 (3): Comparison from the second round to the (d) round [first time]

Compare:

The 2nd and (d+2)th, the 3rd and (d+3)th, the 4th and (d+4)th...

Until the comparison to the (d)th round: dth and (d*2)th

Now, we already have the first 2d sequence of sorted elements:

The first d elements (k: bit order)

respectively less than

The following (d+k) bit element


(4): Comparison from the first round to the (d) round [the second and subsequent rounds]

Similar to (2) and (3) comparison steps, continue to compare until all subsequent elements are compared:

 However, inside this place (step 4):

After each comparison [distinguished by the sequence rules we defined (every d as a group)]

After the last two elements inside

We also perform an operation beyond (2), (3) steps:

Re-traverse all the elements in front of the sequence of each group

That is to say:

After comparing the last two elements of each queue sequence, continue to compare one by one forward

If/whenever the later element is smaller than the previous element in the comparison, put the latter element in front


Here comes the point:

After a total of more than two data ranges are compared, in each round of each comparison: each time

Continue to compare [the smaller element after comparison] with [the element in the previous sequence]

Starting from the element pointed to by i, compare all the elements in front of the entire sequence


In this process, we have completed the entire/all process (process) of the "sorting" operation:

compare one by one

Change the small element to the front position (move the small element to the front)

The large element is swapped to the back position (move to the back when encountering a big one)

 And after comparing more than two data ranges, each time the elements are compared

The operation of comparing all the previous elements (traversing over) is very simple. Add a sentence in the cycle of each comparison of the program:

Keep comparing to the previous element until all the previous elements of this sequence have been compared

This is done:

            for (j = i - d; //第一个元素
                j > 0 && (L.r[0].key < L.r[j].key);
                j -= d)

The for statement design code executed by this program

It is the core and subtlety of  the frame construction of the entire algorithm program operation process


As for how to adjust the different interval sizes d when comparing successively, the method given in the standard answer here is:

Each time through a certain rule dlta[]

(Function? Or what??? He didn't give the corresponding relationship every time here, and I don't know what he is doing) to make some regular changes:

    for (int k = 0; k < t; k++)//t:循环总共趟数
        ShellInsert(L, dlta[k]); 

I'm a bit confused by him here, and I don't know what he's up to


Since I feel that the control method he wrote is a pile of shit, let's take a look at this example of an operation that divides all data into two every time:

The benevolent answer:

//希尔排序
void ShellSort(int A[], int n)
{
    int d, i, j;
    //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
    for (d = n / 2; d >= 1; d = d / 2)
        //步长变化
        for (i = d + 1; i <= n; ++i)
            if (A[i] < A[i - d])
                //需将A[i]插入有序增量子表
            {
                A[0] = A[i];
                //暂存在A[0]
                for (j = i - d; j > 0 && A[0] < A[j]; j -= d)
                    A[j + d] = A[j];
                //记录后移,查找插入的位置
                A[j + d] = A[0];
            }//if
}

According to the preconditions we set up, modify as required: (localize the program)

localization:

void ShellSort(SqList& L)
{
    int  i, j;
    for (int d = L.length / 2; d >= 1; d = d / 2)
        //步长变化

        for (i = d + 1; i <= L.length; ++i)
            if (L.r[i].key < L.r[i - d].key)
            {
                L.r[0] = L.r[i];
                for (j = i - d; j > 0 && L.r[0].key < L.r[j].key; j -= d)
                    L.r[j + d] = L.r[j];
                L.r[j + d] = L.r[0];
            }//if
}

From this point of view, in fact (actually), the program used to control the compensation d of each continuous comparison only needs a paragraph:

    for (int d = L.length / 2; d >= 1; d = d / 2)

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/130310206