思路

核心思想就是去重和排序
就看去重和排序怎么进行了,哪个在前,哪个在后。

1

简单排序,排序过程中去重 ——————未验证
可以用插入排序,有重复值的时候continue,进行下一个数据的排序。
用折半插入感觉更爽点。哈哈。
其他的冒泡选择什么之类的也可以啦,但是插入最对这个题的胃口的了。读一个数,插入一个,免得重新遍历一遍。

int insert_sort(int a[], int n)
{
    int i, j, low, high, mid, temp;
    for (i = 0; i < n; i++) {
        scanf("%d", &a[i]);

        temp = a[i];
        low = 0;
        high = i - 1;
        mid = (high + low) / 2;

        while(low < high) {
            if (temp = a[mid]) {
                break;
            } else if (temp < a[mid]) {
                high = mid -1;
            } else {
                low = mid + 1;
            }

        for (j = i; j > high + 1; j--) {
            a[j] = a[j - 1];
        }
        a[j] = temp;
        } 
    }

    return 0;
}

2

桶排序
a.用1000个桶来统计每个数据的出项次数,输出的时候进行去重。(直接桶排序)
b.用多个桶,每个桶进行插入排序,排序过程中进行去重。(常规桶排序)

a.直接桶排序代码: ——————验证ac

#include<stdio.h>
#include<string.h>

int hash[1001];

int main()
{
    int n = 0, i = 0, num = 0;

    while(scanf("%d", &n) != EOF) {
        memset(hash, 0, sizeof(hash));
        for(i = 0; i < n; i++) {
            scanf("%d", &num);
            hash[num]++;
        }

        for (i = 1; i < 1001; i++) {
            if (hash[i])
                printf("%d\n", i);
        }
    }

    return 0;
}

b.桶排序加插入排序。 ——————未验证
四个桶来搞吧,个位,十位,百位,千位。怎么有点像基数排序了。得用链表啊。
typedef struct _bucketNum{
int num;
_bucketNum *next;
}bucketNum;
int bucket_sort(int a[], int numLen, int bucketLen)
{
int i, temp, bucket;

bucketNum **bucketPoint = (bucketNum **)malloc(bucketLen * sizeof(bucketNum *));
if (!bucketPoint) {
    return -1;
}

for (i = 0; i < bucketLen; i++) {
    bucketPoint[i] = (bucketNum *)malloc(sizeof(bucketNum));
    if (!bucketPoint[i]) {
        while(--i) free(bucketPoint[i]);
        free(bucketPoint);
        return -1;
    }

    bucketPoint[i]->num = 0;
    bucketPoint[i]->next = null;
}

for (i = 0; i < numLen; i++) {
    scanf("%d", &temp);

    bucketNum *numNode = (bucketNum *) malloc(sizeof(bucketNum));
    numNode->num = temp;
    numNode->next = null;

    bucket = getBucketNum(numNode->num);//getBucketNum获取位数,就不实现了吧,挺简单的。
    bucketPointTemp = bucketPoint[bucket];
    if (!bucketPointTemp ->next]) {
        bucketPointTemp ->next = numNode;
        bucketPoint[bucket]->num++;
    } else {
        while(!bucketPointTemp->next) {
            if (bucketPointTemp->next->num == numNode->num) {
                free(numNode);
                break;
            } else (bucketPointTemp->next->num > numNode->num) {
                numNode->next = bucketPointTemp->next;
                bucketPointTemp>next = numNode;
                bucketPoint[bucket]->num++;
            }
            bucketPointTemp = bucketPointTemp->next;
        }
    }

    for (i = 0; i < bucketLen ; i++) {
         bucketPointTemp = bucketPointTemp[i];
        while (!bucketPointTemp->next) {
            printf("%d\n", bucketPointTemp->next->num);
            bucketPointTemp = bucketPointTemp->next;
            bucketPoint[bucket]--;
        }
    }

freeBucket(bucketPoint);//用完后要全部释放。实现这里就不写了。。。

return 0;

}

```
eg:
直接桶排序最简单,插入排序然后去重其次,常规桶排序最长了。
b的桶排序这个并不是针对N<=1000的情况写的。
思考了下这题的变体,如果N比较小,比如说100,并且数据集中分块(10附近一堆,100附近一堆,300一堆这种),用直接桶排序,就是特别合适了。用几个桶就比较合适了,每个桶N个,空间比1000肯定小很多。

其实就是空间和时间的平衡,在平衡中找到最优方式。
直接映射肯定是最方便的,但是空间消耗是最大的;所以需要更改映射方案,但是代价就是增加了一部分的时间开销。