Table of contents
Problem: Missing operations to move elements before inserting them
Project 2: (final product, result)
(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]
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
- Put the second element into the sentinel
- The first element covers the second element
- 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 overIn 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)