各种排序算法的实现

排序算法总结

最近在看算法导论,结合网上的信息总结一下排序算法。
相关文章:
http://blog.csdn.net/xiazdong/article/details/8462393
关于算法的不稳定性不是很理解,需要进一步加强。
https://visualgo.net/
很形象

排序算法复杂度

    int a[n] = { 6, 9, 2, 1 };
    int b[n] = { 1, 2, 6, 9 };
    int c[n] = { 9, 6, 2, 1 };

插入排序

void insert_sort(int arr[])
{
    cout << "insert sort:  "<<endl;
    for (int i = 1; i < n; ++i)
    {
        int j = i - 1;
        int key = arr[i];
        while (j>=0 && arr[j] > key)
        {
            arr[j + 1] = arr[j];//将key之前的序列中大于key的值向后移动一位
            --j;
        }
        arr[j + 1] = key;//将key移动到前边没有比key大的值得位置上
        print_arr(arr);
    }
}

6 9 2 1
6 9 2 1 ->6 9 2 1
6 9 2 1 ->2 6 9 1
2 6 9 1 ->1 2 6 9

冒泡排序

void bubble_sort(int a[])
{
    cout << "bubble_sort: " << endl;
    int temp;
    for (int i = 0; i < n-1; ++i)
    {
        for (int j = n-1; j > i; --j)//要逆着排,这样才能把最小的排在最前边
        {
            if (a[j] < a[j-1])
            {
                temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
            }
            print_arr(a);
        }
    }
}

6 9 2 1
6 9 2 1 -> 6 9 1 2
6 9 1 2 -> 6 1 9 2
6 1 9 2 -> 1 6 9 2
1 6 9 2 -> 1 6 2 9
1 6 2 9 -> 1 2 6 9
1 2 6 9 -> 1 2 6 9

选择排序

void select_sort(int a[])
{
    cout << "select sort:  " << endl;
    for (int i = 0; i < n - 1; ++i)
    {
        int min = i;
        for (int j = i + 1; j < n; ++j)
        {
            if (a[j] < a[min])
                min = j;
        }
        swap(a[i], a[min]);
        print_arr(a);
    }
}

6 9 2 1
6 9 2 1 ->6 9 2 1
6 9 2 1 ->2 9 6 1
2 9 6 1 ->1 9 6 2
1 9 6 2 ->1 6 9 2
1 6 9 2 ->1 2 9 6
1 2 9 6 ->1 2 6 9

/快速排序

int partition(int a[], int p, int q)
{
    int i = p - 1;
    int pivot = a[q];
    for (int j = p; j < q ; ++j)
    {
        if (a[j] <= pivot)
        {
            i++;
            swap(a[i], a[j]);//让子序列中的小于pivot的数放在前边
        }
    }
    swap(a[i + 1], a[q]);
    return i + 1;
}

void rescursive_quicksort(int a[], int p, int q)
{
    if (p < q)
    {
        int r = partition(a, p, q);
        rescursive_quicksort(a, p, r-1);
        rescursive_quicksort(a, r + 1, q);
        print_arr(a);
    }
}

void quick_sort(int a[])
{
    rescursive_quicksort(a, 0, n-1);
}

归并排序

void merge(int a[], int p, int q, int m)
{
    int n1 = m - p + 1;
    int n2 = q - m;

    int *left = new int[n1];
    int *right = new int[n2];

    for (int i = 0; i < n1; ++i)
        left[i] = a[p + i];
    for (int i = 0; i < n2; ++i)
        right[i] = a[m + i +1];

    ////////////合并/////////
    int i = 0;
    int j = 0;
    int k = p;

    while (i<n1 && j < n2 && k<n)
    {
        if (left[i] < right[j])
            a[k++] = left[i++];
        else
            a[k++] = right[j++];
    }
    while (i < n1) /* left[] is not exhausted */
         a[k++] = left[i++];
    while (j < n2) /* right[] is not exhausted */
         a[k++] = right[j++];
    print_arr(a);
}

void recursive_merge_sort(int a[], int p, int q)
{
    if (p < q)
    {
        int m = (p + q) / 2 ;
        recursive_merge_sort(a, p, m);
        recursive_merge_sort(a, m + 1, q);
        merge(a, p, q, m);
        print_arr(a);
    }
}

void merge_sort(int a[])
{
    cout << "merge sort: " << endl;
    recursive_merge_sort(a, 0, n - 1);
}

堆排序
两部分:(1) 形成最大堆(最顶端数最大),从底部向上计算
(2)将top移到最末,对于0~n-2的数组进行处理,形成新的最大堆

void heap_adjust(int a[], int s, int length)//序号s为根节点
{
    int temp = a[s];
    int child = 2 * s + 1;
    while (child < length)
    {
        if (child + 1<length && a[child]<a[child + 1])//比较两个子节点大小,得到值大的子节点
            ++child;
        if (a[s] < a[child])//如果根节点的值小于子节点的值,替换值并且更新根节点
        {
            a[s] = a[child];
            s = child;
            child = 2 * s + 1;
        }
        else
            break;
    a[s] = temp;//给以前的子节点(新的根节点赋原根节点的值)
    }
    print_arr(a);
}

void build_max_heap(int a[])
{
    for (int i = (n - 1) / 2; i >= 0; --i)//i为根节点序号,从底部算到上部
        heap_adjust(a, i, n);
}

void heap_sort(int a[])
{
    build_max_heap(a);
    for (int i = n - 1; i > 0; --i)
    {
        int temp = a[i];//把最后的值与第一个值(最大)替换
        a[i] = a[0];
        a[0] = temp;
        heap_adjust(a, 0, i);///对0~i的长度的堆进行调整
    }
    print_arr(a);
}

希尔排序
变步长的插入排序,这里我用的步长为n/2,n/4,…1

void shell_sort(int a[])
{
    for (int step = n; step > 0; step=step/2)//变步长的插入排序
    {
        for (int i = step; i < n; ++i)
        {
            int key = a[i];
            int j = i-step;
            while ( j>= 0 && a[j]>key)
            {
                a[j + step] = a[j];
                j=j-step;
            }
            a[j + step] = key;
        }
        print_arr(a);
    }
}

计数排序
开辟一个count计数数组,统计原数组各个数的频数,累加得到累积频数,减一即在新数组中的位置。

void counting_sort(int a[],int k)
{

    //int max = 0;
    //for (int i = 0; i<n; ++i)
    //{
    //  if (a[i]>max)
    //      max = a[i];
    //}
    //k = max + 1;

    int *count = new int[k];
    int *b = new int[n];

    for (int i = 0; i < k; ++i)
        count[i]=0;
    for (int i = 0; i < n; ++i)
        ++count[a[i]];
    for (int i = 1; i < k; ++i)//从1开始算哦
        count[i] = count[i] + count[i - 1];//统计不比a[i]大的数的个数,就是a[i]在新的数组中的位置
    for (int i = n-1; i >=0; --i)
    {
        count[a[i]]--;//先减1,从零开始计数
        b[count[a[i]]] = a[i];
    }
    print_arr(b);
    delete count;
    delete b;
}

基数排序
先比个位(计数排序),然后依次十位,百位…

int* getBit(int a[], int bit_num)
{
    int* b=new int[n];

    for (int i = 0; i < n; ++i)
    {
        int total_bit_num = 0;
        for (int no = a[i]; no > 0; no = no / 10)
            total_bit_num++;
        int p = pow(10, bit_num);
        b[i] = a[i] /p %10;
    }
    return b;
}
void radix_sort(int a[])
{
    int max = find_max(a);
    int bit_num = 0;
    for (int i = max; i > 0; i = i / 10)
        bit_num++;

    int *num;
    int *temp = new int[n];
    int count[10];

    for (int j = 0; j < bit_num; ++j)
    {
        for (int i = 0; i < 10; ++i)//清空计数数组
            count[i] = 0;
        num = getBit(a, j);//得到个位,十位...

        for (int i = 0; i < n; ++i)
            ++count[num[i]];                                   
        for (int i = 1; i < 10; ++i)//从1开始算哦
            count[i] = count[i] + count[i - 1];//统计不比a[i]大的数的个数,就是a[i]在新的数组中的位置
        for (int i = n-1; i >= 0 ; --i)//倒计算,假设两个相同的3正序算,第一个3会被放在后边,打乱了以前的排序
        {
            temp[count[num[i]]-1] = a[i];//先减1,从零开始计数
            count[num[i]]--;
        }
        for (int i = 0; i < n; ++i)
            a[i] = temp[i];
        print_arr(a);
    }
    delete num;
    delete temp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值