PTA浙江大学数据结构习题——第八周

排序1 排序

方法一:插入排序
O(N^2)

#include 

using namespace std;

const int N = 100010;

int n;
int a[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    
    for (int i = 1; i < n; i ++)
    {
        int tmp = a[i];
        int j;
        for (j = i; j > 0 && a[j - 1] > tmp; j --)
                a[j] = a[j - 1];
        a[j] = tmp;
    }
    
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
    return 0;
}

方法二:希尔排序
O(N^2)

#include 

using namespace std;

const int N = 100010;

int n;
int a[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    
    for (int d = n / 2; d; d /= 2)
        for (int i = d; i < n; i ++)
        {
            int tmp = a[i];
            int j;
            for (j = i; j >= d && a[j - d] > tmp; j -= d)
                a[j] = a[j - d];
            a[j] = tmp;
        }
    
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
    return 0;
}

方法三:堆排序
O(NlogN)

#include 

using namespace std;

const int N = 100010;

int n;
int a[N];

// 将以root为根节点的堆调整成大根堆
void precdown(int root, int len)
{
    int tmp = a[root];
    int parent, child;
    
    for (parent = root; (parent * 2 + 1) < len; parent = child)
    {
        child = parent * 2 + 1; // 左儿子节点
        if (child + 1 < len && a[child + 1] > a[child])   child ++;
        
        if (a[child] > tmp)
            a[parent] = a[child];
        else    break;
    }
    a[parent] = tmp;
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    
    // 遍历所有根节点,建立大根堆
    for (int i = n / 2 - 1; i >= 0; i --)
        precdown(i, n);
    
    // 每次将最大值与最后一个节点交换,然后维护一个长度 - 1的新大根堆
    for (int i = n - 1; i; i --)
    {
        swap(a[0], a[i]);
        precdown(0, i);
    }
    
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
    return 0;
}

方法四:归并排序

递归算法

O(NlogN)

#include 

using namespace std;

const int N = 100010;

int n;
int a[N], tmp[N];

void merge_sort(int a[], int l, int r)
{
    if (l >= r) return;
    
    int mid = l + r >> 1;
    merge_sort(a, l, mid), merge_sort(a, mid + 1, r);
    
    int i = l, j = mid + 1, k = l;
    while (i <= mid && j <= r)
    {
        if (a[i] > a[j])    tmp[k ++] = a[j ++];
        else    tmp[k ++] = a[i ++];
    }
    while (i <= mid)    tmp[k ++] = a[i ++];
    while (j <= r)  tmp[k ++] = a[j ++];
    
    i = k = l;
    while (k <= r)  a[i ++] = tmp[k ++];
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    
    merge_sort(a, 0, n - 1);
    
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
    return 0;
}

非递归算法

#include 

using namespace std;

const int N = 100010;

int n;
int a[N], tmp[N];

void merge(int a[], int tmp[], int l, int r, int r_end)
{
    int l_end = r - 1;
    
    int i = l, j = r, k = l;
    while (i <= l_end && j <= r_end)
    {
        if (a[i] <= a[j])   tmp[k ++] = a[i ++];
        else    tmp[k ++] = a[j ++];
    }
    while (i <= l_end)  tmp[k ++] = a[i ++];
    while (j <= r_end)  tmp[k ++] = a[j ++];
    
    i = k = l;
    while (i <= r_end)  a[i ++] = tmp[k ++];
}

void merge_pass(int a[], int tmp[], int len)
{
    int i;
    for (i = 0; i <= n - 2 * len; i += 2 * len)
        merge(a, tmp, i, i + len, i + 2 * len - 1);
    if (i + len < n)
        merge(a, tmp, i, i + len, n - 1);
    else
        for (int j = i; j < n; j ++)
            tmp[j] = a[j];
}

void merge_sort()
{
    int len = 1;
    while (len < n)
    {
        merge_pass(a, tmp, len);
        len *= 2;
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    
    merge_sort();
    
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
    return 0;
}

排序2 Insert or Merge

分别用插入排序和归并排序,每一步操作后检查当前排序结果与所给序列是否一致。

#include 
#include 

using namespace std;

const int N = 110;

int n;
int a[N], tmp[N], target[N];
bool merge_flag;

bool match(int a[], int target[])
{
    for (int i = 0; i < n; i ++)
        if (a[i] != target[i])
            return false;
    return true;
}

void print_out(int a[])
{
    for (int k = 0; k < n - 1; k ++)
        printf("%d ", a[k]);
    cout << a[n - 1];
}

bool insert_sort(int a[], int target[])
{
    bool flag = false;
    for (int i = 1; i < n; i ++)
    {
        int t = a[i];
        int j;
        for (j = i; j > 0 && a[j - 1] > t; j --)
            a[j] = a[j - 1];
        a[j] = t;
        
        if (flag)
        {
            puts("Insertion Sort");
            print_out(a);
            return true;
        }
        
        flag = match(a, target);
    }
    return false;
}

void merge(int a[], int tmp[], int l, int r, int r_end)
{
    int l_end = r - 1;
    int i = l, j = r, k = l;
    while (i <= l_end && j <= r_end)
    {
        if (a[i] <= a[j])   tmp[k ++] = a[i ++];
        else    tmp[k ++] = a[j ++];
    }
    while (i <= l_end)  tmp[k ++] = a[i ++];
    while (j <= r_end)  tmp[k ++] = a[j ++];
    
    i = k = l;
    while (i <= r_end)  a[i ++] = tmp[k ++];
}

void merge_pass(int a[], int tmp[], int len)
{
    int i;
    for (i = 0; i <= n - 2 * len; i += 2 * len)
        merge(a, tmp, i, i + len, i + 2 * len - 1);
    if (i + len < n)
        merge(a, tmp, i, i + len, n - 1);
    else
        for (int j = i; j < n; j ++)
            tmp[j] = a[j];
}

void merge_sort()
{
    int len = 1;
    while (len < n)
    {
        merge_pass(a, tmp, len);
        len *= 2;
        
        if (match(a, target))
        {
            merge_pass(a, tmp, len);
            puts("Merge Sort");
            print_out(a);
            return;
        }
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    for (int i = 0; i < n; i ++)    cin >> target[i];
    
    memcpy(tmp, a, sizeof a);
    if (!insert_sort(a, target))
    {
        memcpy(a, tmp, sizeof a);
        memset(tmp, 0, sizeof tmp);
        merge_sort();
    }
    
    return 0;
}

排序3 Insertion or Heap Sort

#include 
#include 

using namespace std;

const int N = 110;

int n;
int a[N], target[N], backup[N];
bool insert_flag, heap_flag;

void print_out()
{
    for (int i = 0; i < n - 1; i ++)
        printf("%d ", a[i]);
    cout << a[n - 1];
}

bool match()
{
    for (int i = 0; i < n; i ++)
        if (a[i] != target[i])
            return false;
    return true;
}

bool insert_sort()
{
    for (int i = 1; i < n; i ++)
    {
        int tmp = a[i];
        int j;
        for (j = i; j > 0 && a[j - 1] > tmp; j --)
            a[j] = a[j - 1];
        a[j] = tmp;
        
        if (insert_flag)
        {
            puts("Insertion Sort");
            print_out();
            return true;
        }
        if (match())    insert_flag = true;
    }
    return false;
}

void precdown(int root, int len)
{
    int tmp = a[root];
    int parent, child;
    
    for (parent = root; (parent * 2 + 1) < len; parent = child)
    {
        child = parent * 2 + 1;
        if ((child + 1) < len && a[child + 1] > a[child])   child ++;
        
        if (a[child] > tmp) a[parent] = a[child];
        else    break;
    }
    a[parent] = tmp;
}

bool heap_sort()
{
    for (int i = n / 2 - 1; i >= 0; i --)
        precdown(i, n);
    
    for (int i = n - 1; i; i --)
    {
        swap(a[0], a[i]);
        precdown(0, i);
        
        if (heap_flag)
        {
            puts("Heap Sort");
            print_out();
            return true;
        }
        if (match())    heap_flag = true;
    }
    return false;
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)    cin >> a[i];
    for (int i = 0; i < n; i ++)    cin >> target[i];
    memcpy(backup, a, sizeof a);
    
    if (!insert_sort())
    {
        memcpy(a, backup, sizeof a);
        heap_sort();
    }
    
    return 0;
}

你可能感兴趣的:(数据结构,排序算法,c++)