归并排序

原理

先将序列两两分组,把序列归并为$$\lceil\frac{n}{2}\rceil$$个组,组内单独排序;然后将这些组两两归并,生成$$\lceil\frac{n}{4}\rceil$$个组,组内再单独排序;以此类推,直到只剩下一个组为止。
归并排序的时间复杂度为O(nlogn)
image.png

递归实现

void mergeArray(int A[], int lo, int mid, int hi)
{
    int* temp = new int[hi - lo + 1];
    int i = lo, j = mid + 1;
    int k = 0;
    while (i <= mid && j <= hi)
    {
        if (A[i] <= A[j])
            temp[k ++] = A[i ++];
        else
            temp[k ++] = A[j ++];
    }
    while ( i <= mid)    temp[k ++] = A[i ++];
    while ( j <= hi)     temp[k ++] = A[j ++];
    
    for (int i = lo, k = 0; i <= hi; i ++, k ++)
        A[i] = temp[k];
        
    delete[] temp; 
}

void mergeSort(int A[], int lo, int hi)
{
    if (lo >= hi) return;
    int mid = lo + hi >> 1;
    mergeSort(A, lo, mid);
    mergeSort(A, mid + 1, hi);
    //mergeArray(A, lo, mid, hi);
    sort (A, A + (hi - lo + 1));
}

非递归实现

void mergeArray(int A[], int lo, int mid, int hi) 
{   
    int* temp = new int[hi - lo + 1];
    int i = lo, j = mid + 1;
    int k = 0;
    while (i <= mid && j <= hi)
    {
        if (A[i] <= A[j])
            temp[k ++] = A[i ++];
        else
            temp[k ++] = A[j ++];
    }
    while ( i <= mid)    temp[k ++] = A[i ++];
    while ( j <= hi)     temp[k ++] = A[j ++];
    
    for (int i = lo, k = 0; i <= hi; i ++, k ++)
        A[i] = temp[k];
        
    delete[] temp; 
}

void mergeSort(int A[])   // step 组内元素的个数,step / 2为左子区间元素的个数
{

    for (int step = 2; step / 2 < n; step *= 2) //每 step 个元素元素一组,组内前 step / 2 和后 step / 2 个元素进行合并
    {   
        for (int i = 0; i < n; i +=step)    //对每一组进行操作
        {
            int mid = i + step / 2 - 1; //左子区间的元素个数为 step / 2 个
            if (mid + 1 < n)    //右子区间存在元素则合并
            {
                mergeArray(A, i, mid, min(i + step - 1, n - 1));
            }
        }
    }
}
// 使用sort 函数替代 mergeArray 函数
void mergeSort(int A[])
{
    for (int step = 2; step / 2 <= n; step *= 2)
    {
        for (int i = 0; i < n; i ++)
            sort(A + i, A + min(i + step, n ));    
    }
    
}

//如果下标从0开始
void mergeSort1(int a[])
{
    for (int step = 2; step / 2 <= n; step *= 2)
    {
        for (int i = 0; i < n; i += step)
        {
            int mid = i + step / 2 - 1;
            if (mid + 1 < n)
            {
                merge(a, i , mid, min(n - 1, i + step - 1));
            
        }
    }
}

//如果时间允许,使用sort函数替代merge函数
void mergeSort1(int A[])
{
    for (int step = 2; step / 2 <= n; step *= 2)
    {
        for (int i = 0; i < n; i++)
        {
            sort(A + i, A + min(i + step, n + 1));
        }
    }
}

快速排序

快速排序时间复杂度O(nlogn)

关于随机数

1.所需头文件

#include <stdlib.h>   
#include <time.h>

2.举例

  • rand()函数只能生成[0, RAND_MAX]范围内的整数。
  • RAND_MAXstdlib.h种的一个常数,不同系统环境,该值不同,一般为32767
  • 输入给定范围[a, b]内的随机数,使用rand() % (b - a + 1) + a
  • mian()函数开头加上srand((unsigned)time(NULL));
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <time.h>  
 ​  
 int main()  
 {  
  srand((unsigned)time(NULL));  
  for (int i \= 0; i < 10; i ++)  
  printf("%d ", rand() % (5 \- 1 + 1) + 1);  
     
  return 0;  
 }

实现

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iostream>

using namespace std;

int partition(int A[], int left, int right)
{
    //在[left, right]内生成随机数 
    int p = (round(1.0 *rand() / RAND_MAX * (right - left) + left));
    // int p = rand() % (right - left + 1) + left;
    swap(A[p], A[left]);
    
    int temp = A[left];
    while (left < right)
    {
        while (left < right && A[right] > temp) right --;
        A[left] = A[right];
        while (left < right && A[left] <= temp) left ++;
        A[right] = A[left];
    }
    A[left] = temp;
    return left;    //返回相遇的下标 
}

void quickSort(int A[], int left, int right) 
{
    if (left < right)
    {
        int pos = partition(A, left, right);
        quickSort(A, left, pos - 1);
        quickSort(A, pos + 1, right);
    }
}

int main()
{
    srand((unsigned)time(NULL));
    
    int A[] = {3, 10, 4, 2, 23, 15};
    
    int n = sizeof(A) / sizeof(int);
    
    quickSort(A, 0, n - 1);
    
    for (int x : A)
    {
        printf("%d ", x);
    }
    
    return 0;
}
参考《算法笔记》

雨天
0 声望3 粉丝

独自灿烂