2023数据结构考研复习-排序

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023数据结构考研复习-排序相关的知识,希望对你有一定的参考价值。

2023数据结构考研复习-排序(八)

十大排序算法Java版

史上最全的十大排序算法Java版

插入排序

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

折半插入排序


void InsertSort(int a[] ,int n) 
    int i, j;
    for (i = 2; i <= n; i++)  //依次将A[2]~A[n]插入前面已排序序列
        if (a[i] < a[i-1])  //若A[i]关键码小于其前驱,将A[i]插入有序表
            a[0] = a[i]; //复制为哨兵,A[0]不存放元素
            int low = 1, high = i-1;
            while (low <= high) 
                mid = (low + high) / 2;
                if (a[mid] > a[0])
                    high = mid - 1;
                else
                    low = mid+1;
            
            for (j = i-1; j >= high + 1; j--)  //从后往前查找待插入位置 A[j+1]-A[j];
                a[j+1] = a[j]; //向后挪位
            
            a[high+1] = a[0]; //复制到插入位置
        
    

希尔排序

void ShellSort (int a[], int n) 
    //步长变化
    for (dk = n/2; dk >= 1; dk/=2)
       for (i = dk+1; i <= n; i++) 
           if (a[i] < a[i-dk]) 
               a[0] = a[i];  //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
               for (j = i-dk; j > 0 && a[0] < a[j]; j-=dk) 
                   a[j+dk] = a[j]; //记录后移,查找插入的位置
               
               a[j+dk] = a[0]; //插入
           
        
    

冒泡排序

void BubbleSort (int a[], int n) 
    for (int i = 0; i < n-1; i++) 
        flag = false;
        for (j = n - 1; j > i; j--) 
            if (a[j-1] > a[j]) 
                swap(a[j-1], a[j]);
                flag = true;
            
        
        if (!flag)
            return;
    

快速排序

void QuickSort (int a[], int low, int high) 
    if (low < high) 
        int pivotpos = Partition(A, low, high);
        Partition(A, low, pivotpos-1);
        Partition(A, pivotpos+1, high);
    

void QuickSort (int a[], int low, int high) 
    if (low < high) 
        int pivotpos = Partition(A, low, high);
        Partition(A, low, pivotpos-1);
        Partition(A, pivotpos+1, high);
    

int Partition(int[] a, int low, int high) 
    int 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; //返回存放枢轴的最终位置

选择排序

void selectsort(ElemType A[] ,int n)
    for(i=0;i<n-1;i++) //一共进行n-1趟
        min = i; //记录最小元素位置
        for(j = i+1; j < n; j++)
            if(A[j] < A[min]) min=j; //更新最小元紊位置
        if(min!=i) 
            swap(A[i], A[min]); //封装的swap()函数共移动元素3次
    

堆排序

void BuildMaxHeap (ElemType A[],int len) 
    for(int i = len/2; i > 0; i--) //从i=[n/2]~1,反复调整堆
        HeadAdjust(A, i, len);
    
void HeadAdjust (ElemType A[],int k, int len) //函数HeadAdjust将元素k为根的子树进行调整
    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=i; //修改k值,以便继续向下筛选
        
    
    A[k]=A[3];  //被缔选结点的值放入最终位置   

void HeapSort (ElemType A,int len)
    BuildMaxHeap(A,len) ;
    //初始建堆
    for(i = len; i > 1 ;i--)[
        //n-1趟的交换和建堆过程
        Swap(A[i], A[1]);
        //输出堆顶元素(和堆底元素交换)
        HeadAdjust(A, 1, i-1);//调整,把剩余的i-1个元素整理成堆
    

归并排序

ElemType *B= (ElemType *)malloc((n+1)*sizeof (ElemType)); //辅助数组B
void Merge (ElemType A[],int low,int mid,int high)
    //表A的两段A[low..mid]和A[mid+1..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[i++]; //将较小值复制到A中
        else
            A[k]=B[j++];
    //for
    while(i <= mid) A[k++]=B[i++]; //若第一个表未检测完,复制
    while(j <= high) A[k++]=B[j++]; //若第二个表未检测完,复制


void MergeSort (ElemType A[],int low,int high)
    if(low<high) 
        int mid = (low+high) / 2; //从中间划分两个子序列
        MergeSort(A, low, mid); //对左侧子序列进行递归排序
        MergeSort (A, mid+1, high); //对右侧子序列进行递归排序
        Merge(A, low, mid, high);//归并
    //if

综合应用题

双向冒泡排序算法

编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。

这种排序方法又称双向起泡。奇数趟时,从前向后比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最大的元素移动到序列尾部。偶数趟时,从后往前比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最小的元素移动到序列前端。程序代码如下:

void BubbleSort (int a[], int n) 
    int low = 0, high = n-1;
    bool falg = true;
    while (low < high && flag) 
        flag = false;
        for (i = low; i < high; i++) 
            if (a[i] > a[i+1]) 
                swap(a[i], a[i+1]);
                flag = true;
            
        
        high--;
        for (i = high; i > low; i--) 
            if (a[i] < a[i-1]) 
                swap(a[i], a[i-1]);
                flag = true;
            
        
        low++;
     

奇数移动到偶数前面

已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少).

本题可采用基于快速排序的划分思想来设计算法,只需遍历一次即可,其时间复杂度为O(n),空间复杂度为O(1)。假设表为L [1…n],基本思想是:先从前向后找到一个偶数元素L(i),再从后向前找到一个奇数元素L(j),将二者交换;重复上述过程直到i大于j。

算法的实现如下:

void movie (int a[], int len) 
    int i = 0, j = len - 1;
    while (i < j) 
        while (i < j && a[i] % 2 != 0) i++;
        while (i < j && a[j] % 2 != 1) j--;
        if (i < j)
            Swap(a[i], a[j]);
        i++;
        j--;
    

快排枢纽值随机

试重新编写考点精析中的快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的。

int Partition(int[] a, int low, int high) 
    int rand_index = low + rand() % (high - low + 1);
    Swap (a[rand_index], a[low]); //将枢轴值交换到第一个元素
    int pivot = a[low]; //置当前表中的第一个元素为枢轴值
    int i = low;
    for (int j = low + 1; j <= high; j++) 
        if (a[j] < pivot) //找到后,交换到前面
            swap(a[++i], a[j]);
    
    swap(a[i], a[low]); //将基准元素插入最终位置
    return i;  //返回基准元素的位置

快排找第k小元素

试编写一个算法,使之能够在数组L[1…n]中找出第k小的元素(即从小到大排序后处于第k个位置的元素)。

在这里插入代码片
```![在这里插入图片描述](https://img-blog.csdnimg.cn/52c1812e20c3485c8866655c1de411e4.png)

```cpp
int kth_elem(int a[], int low, int high, int k) 
    int pivot = a[low];
    int low_temp = low;
    int high_temp = high;
    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;
    if (low == k)
        return a[low];
    else if (low > k)
        return kth_elem(a, low_temp, low-1, k);
    else
        return kth_elem(a, low+1, high_temp, k);

荷兰国旗图案

荷兰国旗问题:设有一个仅由红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为O(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗图案。

算法思想:顺序扫描线性表,将红色条块交换到线性表的最前面,蓝色条块交换到线性表的最后面。为此,设立三个指针,其中,j为工作指针,表示当前扫描的元素,i以前的元素全部为红色,k以后的元素全部为蓝色。根据j所指示元素的颜色,决定将其交换到序列的前部或尾部。初始时i=0,k=n-1,算法的实现如下:

void Flag_arrange(color a[], int n) 
    int i = 0, j = 0, k = n-1;
    while (j <= k) 
        switch (a[j]) 
            case RED: Swap(a[i], a[j]); i++; j++; break;
            case White: i++; j++; break;
            case RED: Swap(a[k], a[j]); k--; break;
            // 没有j++防止交换后a[j]仍为蓝色
        

以上是关于2023数据结构考研复习-排序的主要内容,如果未能解决你的问题,请参考以下文章

2023数据结构考研复习-查找

2023数据结构考研复习-查找

2023数据结构考研复习-栈队列和数组

2023数据结构考研复习-栈队列和数组

2023数据结构考研复习-串

2023数据结构考研复习-串