Sorting method of data structure

1. Direct insertion sort.
In order to insert the element L(i) into the pre-ordered subsequence L(1...i-1), the following operations are required. (L[] is used below to represent a table, and L[] is used to represent an element)
1. Find the insertion position k of L(i) in L[1...i-1].
2. Move all the elements in L[k...i-1] back by one position.
3. Copy L(i) to L(k).
In order to realize the sorting of L[1...n], L(2)~L(n) can be inserted into the previously arranged subsequence one by one. Initially, it is assumed that L(1) is a sorted subsequence. sequence.
The following is the code algorithm for direct insertion sort

void InsertSort(ElemType A[],int n){
    
    
    int i,j;
    for(i=2;i<=n;i++)  || 依次将A(2)~A(n)插入到前面已排序序列
        if(A[i].key<A[i-1].key){
    
      ||若A[i]的关键码小于其前驱,需要将A[i]插入有序表
            A[0]=A[i];  ||复制为哨兵,A[0]不存放元素
            for(j=i-1;A[0].key<A[j].key;--j)  ||从后往前找待插入位置
                A[j+1]=A[j];  ||向后挪移
            A[j+1]=A[0];  ||复制到插入位置
        }
}

EG,
Insert picture description here

Two, half insertion sort.
It can be seen from the direct insertion sorting algorithm that two tasks are carried out in each insertion process.
1. Find the position where the element to be inserted should be inserted from the previous seed table;
2. Make room for the insertion position and wait The inserted element is copied to the insertion position in the table.
In the direct insertion sorting algorithm, the elements are always moved while comparing. The following separates the comparison and the movement, that is, first finds the insertion position of the element in half, and then uniformly moves all the elements after the position to be inserted, that is, the half insertion sort .
Because it is a linear table stored sequentially, you can use a binary search to find an ordered sub-table. The code is as follows

void ShellSort (ElemType A[],int n) {
    
    
    int i,j,low,high,mid;
    for(i=2;i<=n;i++) {
    
      ||依次将A(2)~A(n)插入到前面已排序序列
        A[0]=A[i];  ||将A[i]暂存到A[0]
        low=1;high=i-1;  ||设置折半查找的范围
        while(low<=high){
    
      ||折半查找(默认递增有序)![在这里插入图片描述](https://img-blog.csdnimg.cn/20210304015428712.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NDUwMTYzMg==,size_16,color_FFFFFF,t_70#pic_center)

            mid=(low+high)/2;  ||取中间点
            if(A[mid].key>A[0].key) high=mid-1;  ||查找左半子表
            else low=mid+1;  ||查找右半子表
            }
            for(j=i-1;j>=high+1;--j)
                A[j+1]=A[j];  ||统一后移元素,空出插入位置
            A[high+1]=A[0];  ||插入操作
    }
}

EG.
Insert picture description here

3. Hill sorting.
The basic idea of ​​Hill sorting is: first divide the list to be sorted into a number of "special" sub-tables like L[i, i+d, i+2d, ```i+kd], and insert directly into the sub-tables. Sorting, when the elements in the entire table are basically in order, then perform a direct insertion sort on all records. The process is as follows;
first take a step size d1 smaller than n, divide all records in the table into d1 groups, put all records with a distance of multiples of d1 in the same group, and perform direct insertion sort in each group; then take the first For two steps d2<d1, repeat the above process until the obtained dt=1, that is, all records have been placed in the same group, and then perform direct insertion sorting. Because of the good local order at this time, Therefore, the final result can be obtained quickly. So far, the best increment sequence has not been obtained. The city proposed by Hill is d1=n/2, di+1=[d/2], and the last increment is equal to 1.

void ShellSort (ElemType A[],int n){
    
    
    for(dk=n/2;dk>=1;dk=dk/2)  ||步长变化
        for(i=dk+1;i<=n;++i)  
            if[Ai].key<A[i-dk],key){
    
      ||需将 A[i]插入有序增量子表
                 A[0]=A[i];  ||暂存在A[0]
                 for(j=i-dk;j>0&&A[0].key<A[j].key;j-=dk)
                     A[j+dk]=A[j];  ||记录后移,查找插入位置
                 A[j+dk]=A[O];  ||插入
            }
}

EG.
Insert picture description here

Fourth, bubble sorting.
The basic idea of ​​the sorting algorithm is: Suppose the length of the list to be sorted is n, compare adjacent values ​​pairwise from back to front (or from front to back), if it is in reverse order (ie A[i-1]>A[i]), Then swap them until the sequence comparison is complete. We call it a bubbling, and as a result, the smallest element is swapped to the first position of the sequence to be sorted (the element with the smallest keyword is gradually "floating" up to the "water surface" like a bubble). In the next bubbling, the smallest element determined in the previous pass will no longer participate in the comparison, and the sequence to be sorted will be reduced by one element. The result of each bubbling pass puts the smallest element in the sequence at the final position of the sequence.
The algorithm code is as follows

void BubbleSort(ElemType A[],int n){
    
    
    for(i=0;i<n-1;i++){
    
     
        flag=false;  ||表示本趟冒泡是否发生交换的标志 
        for(j=n-1;j>i;j--)  ||一趟冒泡过程
            if(A[j-1].key>A[j].key){
    
      ||若为逆序
                  swap (A[j-1],A[j];  ||交换
                  flag=true;
            }
        if(flag==false)
            return ;  ||本趟遍历后没有发生交换,说明表已经有序
     }
} 

EG
Insert picture description here

Five, quick sort.
Quick sort is an improvement to bubble sort. The basic idea is the basic divide-and-conquer method; any element pivot in the list to be sorted L[1...n] is taken as the benchmark, and the list to be sorted is divided into two independent parts L[1...k-1 through one sorting ] And L[K+1…n] so that all elements in L[1…k-1] are less than pivot, and all elements in L[k+1…n] are greater than or equal to pivot, then pivot is placed in
its final position L On (k), this process is called a one-pass quick sort. Then recursively repeat the above process for the two sub-tables until there is only one element in each part or empty, that is, all elements are placed in their final positions.
The algorithm structure is as follows

void QuickSort(ElemType A[],int low,int high){
    
    
    if (low<high)  ||递归跳出的条件
             int pivotpos=Partition (A,low,high);  ||划分
             QuickSort (A, low, pivotpos-1);  ||依次对两个子表进行递归排序
             QuickSort (A,pivotpos+1,high);
    }
}

Assuming that the first element system in the current table is always used as the pivot value (reference) each time, the elements in the table that are larger than the pivot value must be moved to the right, and the elements smaller than the pivot value must be moved to the left. , So that after one operation, the elements in the table are divided into two by the pivot value.

int Partiion(ElemType A[],int low,int high){
    
    
    ElemType pivot=A[low];  ||将当前表中第一个元素设为枢轴值,对表进行划分
    while (low<high){
    
      ||循环跳出条件
        while(low<high&&A[high]>=pivot) --high; 
        A[low]=A[high];  ||将比枢轴值小的元素移动到左端
        while(low<high&&A[low]<=pivot) ++low;
        A[high]=A[low]||将比枢轴值大的元素移动到右端
    }
    A[low]=pivot;  ||枢轴元素存放到最终位置
    return low;  ||返回存放枢轴的最终位置
}

EG.
Insert picture description here
Insert picture description here

Sixth, simple selection and sorting.
The idea of ​​simple selection sorting: Assuming the sorting table is L[1...n], the i-th sorting is to select the element with the smallest key from L[1...n] to exchange with L[i], and each sorting can determine one The final position of the element, so that the whole sorting can be ordered after n-1 sorting.
The algorithm code is as follows

void SelectSort(ElemType A[],int n){
    
    
    for(i=0;i<n-1;i++){
    
      ||一共进行 n-1趟
        min=i;  ||记录最小元素位置
        for(j=i+1;j<n;j++)  ||在A[i…n-1]中选择最小的元素 
            if(A[j]<A[min)min=j;  ||更新最小元素位置
        if(min!=i)swap(A[i],A[min];   ||与第i个位置交换
    }
}    

Seven, heap sorting.
Heap sort is a tree-shaped selective sorting method. Its characteristics are: in the sorting process, L[1...n] is regarded as a sequential storage structure of a complete binary tree, and the parent node and child node in the complete binary tree are used. The internal relationship between the points, select the element with the largest (or smallest) keyword in the current disordered area.
The definition of heap is as follows: n key sequence L[1...n] is called heap, if and only if the sequence satisfies:
1. L(i)<=L(2i) and L(i)<=L(2i) +1) or 2, L(i)>=L(2i)) and L(i)>=L(2i+1)(1<=i<=n/2])
The pile weighing that satisfies the first case It is a small root pile (small top pile), and a pile that meets the second condition is called a big root pile (large top pile). In the big root pile, the largest element is stored in the root node, and for any non-root node, its value is less than or equal to the value of its parent node. The definition of small root pile is just the opposite, the root node is the smallest element.
The key to heap sorting is to construct an initial heap and build a heap on the initial sequence, which is a process of repeated screening. A complete tree of n nodes, the last node is the child of the [n/2]th node. Filter the subtree rooted at the [n/2]th node (for a large root heap: the key of the root node is smaller than the one with the larger key in the left and right children, then exchange), so that the subtree becomes a heap. Afterwards, filter the subtrees rooted at each node (n/2]-1~1) in turn to see if the value of the node is greater than the value of its left and right child nodes. If not, add the left and right child nodes to the A larger value is exchanged with it. After the exchange, the next-level heap may be destroyed, so continue to use the above method to construct the next-level heap until the subtree rooted at this node constitutes a heap. Repeatedly use the above method of adjusting the pile to build the pile until the root node.
The following is the algorithm code of the big root heap

void BuildMaxHeap(ElemType A[],int Len){
    
    
    forint i=len/2;i>0;i--)
         AdjustDown (A,i,len);
}
void AdjustDown(ElemType A[],int k,int Len){
    
    
    A[0] =A[k];  ||A[0]暂存
    for (i=2*k;i<=len;i*=2){
    
      ||沿 key 较大的子结点向下筛选
         if(i<len&&A[i]<A[i+1])  
             i++;  ||取 key 较大的子结点的下标
         if(A[0]>=A[i]break;  ||筛选结束
         else{
    
    
             A[k]=A[i];  ||将 A[i]调整到双亲结点上
             k=1;  ||修改 k 值,以便继续向下筛选
         }
    }
    A[k]=A[0];  ||被筛选结点的值放入最终位置
}

EG.
Insert picture description here

8. Merge and sort.
"Merge" means to combine two or two; table sequence into a new ordered table. Assuming that the list to be sorted contains n records, it can be regarded as n ordered sub-tables with a length of 1, and then merged in pairs to obtain [n/2] ordered lists with a length of 2 or 1; The two merge.

ElemType *B=(ElemType *)malloc((n+1*sizeof(ElemType)
void Merge(ElemType A[],int low,int mid,int high){
    
    
    for(int k=low; k<=high; k++
        B[k]=A[k];  ||将 A中所有元素复制到 B 中 
    for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
    
    
        if(B [i]<=B[j])  || 比较 B 的左右两段中的元素
             A[k]=B[1++]  ||将较小值复制到A 中 
        else
             A[k]=B[j++];
    }
    while(i<=mid) A[k++]=B[i++];  ||若第一个表未检测完,复制 
    while(i<=high)A[k++]=B[j++];  ||若第二个表未检测完,复制
}

Note; only one of the last two while loops in the above code will execute.

EG.Insert picture description here

The figure below is a comparison of the time complexity, space complexity of each sorting method, and whether the algorithm is stable.

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_54501632/article/details/114339914