• 变长数据项的排序 算法导论8.3 8.3.4(e)


    第一步,先按数据的长度排序,计算出数据的长度(一般大小为正整数),然后按计数排序的方法排序

    第二步,对相同长度的数据进行基数排序。基数排序采用计数排序作为稳定排序。

    这里遇到了一个问题, 第二问对字符串按字典序排列(a<ab<b),这样的话按上面的方法就有问题,因为这个方法先按字符串长度划分字符串数组,排序之后是(a,b,ab),不知道怎么用这个章节的方法解题(知道可以用trie)?

    debug总结:

    1) 参数取名很重要,temp和temp1搞混就会程序崩溃,所以名字需要易于辨别和理解

    2) 如果岔开了思路,待会再继续的话最好重新理一遍。

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    const int N = 10;
    const int M = 26;
    //计数排序假设输入的元素都是0-k之间的整数,k为自然数
    void Counting_Sort_Origin(int *a,int n, int *b, int k){
        int *p = new int[k+1];             //new int[k+1]() 值初始化,所以的都为0.
        for (int i = 0; i < k + 1; ++i)    //内置类型默认初始化的值是不确定的。
            p[i] = 0;
        for (int i = 0; i < n; ++i){
            ++p[a[i]];
        }
        for (int i = 1; i < k + 1; ++i)
            p[i] += p[i - 1];
        for (int i = n-1; i >= 0; --i){
            b[p[a[i]]-1] = a[i]; 
            --p[a[i]];
        }
        delete []p;
    }
    
    void Exer_834(int *a,int *b,int *c, int n){
        int *p = new int[n]();//计数数组
        //三次循环,把整数看成3位数,每位从0到n-1
        for (int m = 0; m < 3; ++m){
            //每个数可以拆为三个关键字,每个关键词进行计数排序
            for (int i = 0; i < n; ++i){
                c[i] = (a[i] / (int)pow(n, m)) % n;
            }
            cout << endl;
            for (int i = 0; i < n; ++i){
                p[i] = 0; 
            }
            for (int i = 0; i < n; ++i){
                ++p[c[i]];
            }
            for (int i = 1; i < n; ++i)
                p[i] += p[i - 1];
            for (int i = n - 1; i >= 0; --i){
                b[p[c[i]] - 1] = a[i];
                --p[c[i]];
            }
            for (int i = 1; i < n; ++i)
                a[i] = b[i];
        }
        delete[]p;
    }
    //原址版计数排序,但是不稳定
    void O_Counting_S(int *a,int n,int k){
        int *p = new int[k + 1]();
        int *loc = new int[k + 1]();
        for (int i = 0; i < n; ++i){
            ++p[a[i]];
        }
        for (int i = 1; i < k + 1; ++i){
            p[i] += p[i - 1];
            loc[i] = p[i];
        }
        //for (int i = 0; i < 10; i++)
        //    cout << p[i] << " ";
        int count = 0;
        while(count<n){
            if (p[a[count] - 1] <= count&&count < p[a[count]])
                ++count;
            else{
                int temp = a[count];
                swap(a[count], a[loc[a[count] - 1]]);
                ++loc[temp-1];
            }
        }
    }
    
    
    int Bits(int num);
    int Nth_digit(int num, int i);
    
    //基数排序中的计数排序模块,多一个参数表示依据哪个位在排序
    //这里把每个位可能取值的可能性省去,用全局变量N表示,即为10
    void Counting_Sort(int *a, int n,int ith){
        int *p = new int[N]();             
        int *temp = new int[n];
        int *temp1 = new int[n];
        for (int i = 0; i < n; ++i)  { temp[i] = a[i]; }   //copy数组
        for (int i = 0; i < n; ++i)  { temp1[i] = Nth_digit(a[i], ith); }
        for (int i = 0; i < n; ++i)  {++p[temp1[i]]; }
        for (int i = 1; i < N; ++i)  { p[i] += p[i - 1]; }
            
        for (int i = n - 1; i >= 0; --i){
            a[p[temp1[i]] - 1] = temp[i];
            --p[temp1[i]];
        }
        delete[]p;
        delete[]temp;
        delete[]temp1;
    }
    
    
    void Radix_Sort(int *a, int n, int k){
        if (n == 0)
            return;
        for (int i = 0; i < k; ++i){
            Counting_Sort(a, n,i);
        }
    }
    
    void Partition_Bybit(int *a,int n,int *group,int k){
        int *temp = new int[n];
        int *temp1 = new int[n];
        int *p = new int[k + 1]();
        for (int i = 0; i < n; i++)      {temp[i] = Bits(a[i]);}
        for (int i = 0; i < n; ++i)      { ++p[temp[i]]; }
        for (int i = 1; i < k + 1; ++i)  { p[i] += p[i - 1]; }
        for (int i = 0; i < k + 1; ++i)  { group[i] = p[i]; }
        for (int i = 0; i < n; ++i)      { temp1[i] = a[i]; }
    
        for (int i = n-1; i >=0; --i){
            a[p[temp[i]] - 1] = temp1[i];
            --p[temp[i]];
        }
        delete[]p;
        delete[]temp;
        delete[]temp1;
    }
    
    
    void Ex_83_a(int *a, int n){
        int *temp = new int[n];
        int max_bit = 0;
        for (int i = 0; i < n; i++){
            temp[i] = Bits(a[i]);
            if (temp[i]>max_bit)
                max_bit = temp[i];
        }
        int *group = new int[max_bit + 1]();
        Partition_Bybit(a, n, group, max_bit);
        for (int i = 0; i < max_bit;++i){
            Radix_Sort(a + group[i], group[i + 1] - group[i], i+1);
        }
    }
    //把每个数字的位数记录下来
    
    int Nth_digit(int num,int i){
        return (num / (int)pow(N, i)) % N;
    }
    
    
    int Bits(int num){
        int count = 1;
        while (num / 10){
            ++count;
            num /= 10;
        }
        return count;
    }
    
    void Counting_Sort_S(int *a, int n, int *b, int ith){
        int *p = new int[N]();
        int *temp = new int[n];
        int *temp1 = new int[n];
        for (int i = 0; i < n; ++i)  { temp[i] = a[i]; }   //copy数组
        for (int i = 0; i < n; ++i)  { temp1[i] = Nth_digit(a[i], ith); }
        for (int i = 0; i < n; ++i)  { ++p[temp1[i]]; }
        for (int i = 1; i < N; ++i)  { p[i] += p[i - 1]; }
    
        for (int i = n - 1; i >= 0; --i){
            a[p[temp1[i]] - 1] = temp[i];
            --p[temp1[i]];
        }
        delete[]p;
        delete[]temp;
        delete[]temp1;
    }
    
    
    int main(){
        int a[15] = { 555, 444, 333, 222, 111,5, 4, 3, 2, 1, 11, 22, 33, 44, 55 };
    
        Ex_83_a(a, 15);
    
        for (int i = 0; i < 15; i++)
        cout << a[i]<<" ";
    
    }
  • 相关阅读:
    加分二叉树
    香甜的黄油 Sweet Butter
    09.22今日暂时停更题解
    能量项链
    转圈游戏
    字串变换
    关押罪犯
    选择客栈
    神经网络
    未整理算法的总结
  • 原文地址:https://www.cnblogs.com/Nastukashii/p/4412756.html
Copyright © 2020-2023  润新知