[The seventeenth day of the C language inspector training camp] The sorting questions in the postgraduate entrance examination (Part 2)----selection sorting, merge sorting, heap sorting

foreword

The content introduced today includes selection sorting, merge sorting, and heap sorting. Overall, it is not difficult. When actually writing code questions, you need to pay attention to some details. There is one more thing that needs to draw our attention. Sorting type code questions are usually scored according to time complexity and space complexity. If you choose a very suitable algorithm, then these two complexities can definitely be easily achieved, so when we write questions, we must, if there is 稳中求精no If you want to strike accurately, choose one you know, 退而求其次, 推荐熟练掌握快速排序算法, if you think these algorithms are too difficult to understand, you can only be familiar with the code, but you must understand the idea of ​​​​the algorithm, so that you can’t write it but you can understand it! Let's start today's content, let's take a look at the real question first.
insert image description here
This question can achieve the desired effect by using quick sort or heap sort.

1. Selection sort

Selection sort is divided into: simple selection sort, heap sort.
Idea: Simple selection sorting principle: Assuming that the sorting table is L[1...n], the i-th sorting is to select the element with the smallest key from L[i...n] and exchange it with L(i), and each sorting can be determined The final position of an element, so that the entire sorted table can be ordered after n -1 sorting.
First assume that the zeroth element is the smallest, and assign the subscript 0 to min (min chooses the subscript of the smaller one), and when P is compared, it is compared from element 1 to element 9, whichever is smaller , assign its subscript to min, and after a round of comparison, exchange the element corresponding to min with element i, as shown in the following table. The first round confirms that 2 is the smallest, and exchanges 2 with element 3 at the beginning of the array. In the second round, we initially thought that 87 was the smallest. After a round of comparison, we found that 3 was the smallest. At this time, we exchanged 87 and 3. This continues until the array is sorted.

Note: selection sorting and bubble sorting are both composed of two loops. If you don't understand the ideas of the two, it is easy to confuse! Needs more attention.
If the text is a little hard to understand then we can take a look at the animation!
insert image description here
Code combat:

//选择
//针对选择排序循环条件
//每次找出一个位置,然后拿其余元素与其对比找出目前无序序列中最大或最小的元素放在选出的位置
//需要经过n-1次筛选(所以外层循环为n-1)
//从选出位置的下一个元素开始对比,直到列表中无序部分的末尾(所以内层循环那样写)
//针对算法思想:
//选择排序每次选出一个最大的元素或者最小的元素(看升序还是降序),放在当前无序的部分的第一个位置
//每选出一个就将有序部分向后扩展一位,继续选元素,直到整个序列有序。
void SelectSort(int *p){
    
    
    for(int i=0;i<maxSize-1;i++){
    
    
        for(int j=i+1;j<maxSize;j++){
    
    
            if(p[i]>p[j]){
    
    
                int temp=p[i];
                p[i]=p[j];
                p[j]=temp;
            }
        }
    }
}

2. Merge sort

There are many kinds of merge sorting, the most common is the two-way merge of internal sorting, in addition to the multi-way balanced merging of external sorting. The main introduction here is the two-way merge.
Idea: Merge sorting uses the idea of ​​recursion. In the two-way merge sorting, the sequence to be sorted is first grouped, and the length of the group is divided into 1/2 of the original length each time. When there is only one element, it starts to be divided into two groups. merge. When the merge is complete, the sequence becomes ordered. As shown in the picture
insert image description here
, note:当合并数组时需要注意合并序列的下标(索引)并不是从0开始或者到len-1结束

If the text is a little hard to understand then we can take a look at the animation!
insert image description here
Code combat:

//归并排序用到的合并函数
//在写这个函数的时候一定要注意,开始结束条件不再是0与len-1了,而是从外部传进来的索引
void Merger(int *p,int l,int midde,int r){
    
    
    static int B[maxSize];
    int i=0,j=0,z=0;
    //最后将pB中的元素放进p;
    for(i=l;i<=r;i++){
    
    
        B[i]=p[i];
    }
    for(i=l,j=midde+1,z=l;i<=midde&&j<=r;z++){
    
    
        if(B[i]<B[j]){
    
    
            p[z]=B[i];
            i++;
        }else{
    
    
            p[z]=B[j];
            j++;
        }
    }
    while(j<=r){
    
    
        p[z++]=B[j++];
    }
    while(i<=midde){
    
    
        p[z++]=B[i++];
    }
}
//归并排序
//归并排序思想:
//归并排序有许多种类型,常考的就是路归并,先分组刚开始
//一组一个元素,然后将分的组逐步两两合并,最后得到有序序列
//本函数传进来的是数列的左右下标。
void MergerSort(int *p,int l,int r){
    
    
    if(l<r){
    
    
        // 这个midde始终指向中间位置
        int midde=(l+r)/2;
        MergerSort(p,l,midde);
        MergerSort(p,midde+1,r);
        //合并序列
        Merger(p,l,midde,r);
    }
}

3. Heap sort

Idea: Heap is a special tree-like data structure in computer science. If it satisfies the following characteristics, it can be called a heap: "Given any node P and C in the heap, if P is the parent node of C , then the value of P is less than or equal to (or greater than or equal to) the value of C." If the value of the parent node is always less than or equal to the value of the child node, the heap is called the minimum heap (min heap); conversely, if the parent node The value of is always greater than or equal to the value of the child node, then the heap is called the maximum heap (max heap). The topmost node in the heap is called the root node, and the root node itself has no parent node. Usually in work, we call the smallest heap a small root heap or a small top heap, and the largest heap a big root heap or a big top heap.

When implementing the algorithm, we need to write two functions, one function is responsible for generating the heap with the incoming node as the root node, and the other function is responsible for extracting the elements at the top of the heap, one at a time, and put them in the current unordered part after extraction The last position of the tree, and then based on the root node of the tree, the tree is adjusted to a large root heap or a small root heap until the root node of the heap is realized for every number. At this point the original sequence will become orderly.
Note:在将树调整为堆的时候需要注意,边界条件是严格的,如果不严格将会导致排序过的元素重新回到堆中,将会破坏堆的结构,导致排序出现问题。 When generating a heap, the boundary condition is the position of the last element of the unordered part.

If the text is a bit confusing then watch the animation!
insert image description here
Code combat:

//堆排序
//排序思想:
//先将数据初始化成为大根堆或者小根堆的形式(大根堆是大的在作为父节点,小根堆是小的作为父节点)
//大根堆用于升序排序,小根堆用于降序
//初始化完毕之后,开始选择元素,每次选出根节点元素换到当前无序部分最后位置,然后重新生成大根堆
//(这里需要注意的是生成大根堆之后选择元素时最大只需要遍历到树的深度即可)

//DeliverBigHeap函数是调整大根堆的函数(每次只调节一颗树)k为当前根节点元素所在的下标(maxIndex是无序部分长度)
//这里的maxIndex限制条件是严格的(如果在判断的时候小了或者大了,均会造成数据混乱)
//所以记住,当选出一个元素的之后,需要将这个元素移到有序段开头,并及时把无序的部分长度减1.
void DeliverBigHeap(int *p,int k,int maxIndex){
    
    
    int sonIndex=k*2+1;
    //调整堆
    while (sonIndex<=maxIndex){
    
    
    	//先比较两个子节点哪个大,把大的拿上来!
        if(sonIndex+1<=maxIndex&&p[sonIndex]<p[sonIndex+1]){
    
    
            sonIndex++;
        }
        //父子换位置
        if(p[k]<p[sonIndex]){
    
    
            int temp=p[k];
            p[k]=p[sonIndex];
            p[sonIndex]=temp;
            // 交换之后继续探测上一个根节点
            k=sonIndex;
            sonIndex=k*2+1;
        }
        //如果一样大或者父节点大,那么该子树已经符合堆定义,直接跳出!
        else{
    
    
            break;
        }
    }
}

void HeapSort(int *p,int len){
    
    
    int temp;
    for(int i=(len-1)/2;i>=0;i--){
    
    
        DeliverBigHeap(p,i,len-1);
    }
//    temp=p[len-1];
//    p[len-1]=p[0];
//    p[0]=temp;
//    printMyarray(p);


//---------------------------------写法1
//    int i;
//    for(i=len-1;i>0;i--){
    
    
//        temp=p[i];
//        p[i]=p[0];
//        p[0]=temp;
//        //
//        DeliverBigHeap(p,0,i-1);
//    }
//    temp=p[i];
//    p[i]=p[0];
//    p[0]=temp;
//----------------------------------写法2
    temp=p[len-1];
    p[len-1]=p[0];
    p[0]=temp;
    for(int i=len-2;i>0;i--){
    
    
        DeliverBigHeap(p,0,i);
        temp=p[i];
        p[i]=p[0];
        p[0]=temp;
    }
//----------------------------------错误写法
//错误原因:因为在调整大根堆的时候实际边界是i-1,这里写成i了
//这在一定情况下容易造成已经排好序的元素再回到树中,然后占据不该占据的位置。
//    for(int i=len-2;i>0;i--){
    
    
//        temp=p[i];
//        p[i]=p[0];
//        p[0]=temp;
//        DeliverBigHeap(p,0,i);
//    }
//    temp=p[len-1];
//    p[len-1]=p[0];
//    p[0]=temp;
}

Wow, sorting algorithm, a painful lesson, although I felt that I learned it well before, but it is nothing under the catalysis of time! The animation is a bit fast, but the complete process exceeds 5M, see the complete animation portal (heap sort) , and the other ten sorts !

Guess you like

Origin blog.csdn.net/apple_51931783/article/details/129219247