#include <stdlib.h>
#include <stdio.h>
#define MAX 100005
typedef long ElementType;
//快速排序-直接调用库函数
//简单整数排序
int compare ( const void *a, const void *b ) {
return ( *(ElementType*)a - *(ElementType*)b );
}
//一般情况下,对结构体Node中的某键值key排序
//struct Node {
// ElementType key1, key2;
//} A[MAX];
按key1降序排列,若key1相等,则按key2升序排列
//int compare2keys ( const void *a, const void *b ) {
// int k;
// if( ((const struct Node*)a)->key1 < ((const struct Node*)b)->key1 )
// k = 1; //1说明交换
// else if ( ((const struct Node*)a)->key1 > ((const struct Node*)b)->key1 )
// k = -1; //-1交换
// else {
// if ( ((const struct Node*)a)->key2 < ((const struct Node*)b)->key2 )
// k = -1;
// else
// k = 1;
// }
// return k;
//}
//快速排序
void Swap ( ElementType *a, ElementType *b ) {
ElementType tmp = *a;
*a = *b;
*b = tmp;
}
//元素过少时,使用这个插入排序
void Insertion_Sort( ElementType A[], int N ) {
int P, i;
ElementType Tmp;
for( P = 1; P < N; P++ ) {
Tmp = A[P]; //取出未排序序列中的第一个元素
for( i = P; i > 0 && A[i - 1] > Tmp; i-- )
A[i] = A[i - 1]; //依次与已排序序列中的元素比较并右移
A[i] = Tmp; //插入到合适的位置
}
}
ElementType Median3 ( ElementType A[], int Left, int Right ) {
int Center = ( Left + Right ) / 2;
if ( A[Left] > A[Center] )
Swap( &A[Left], &A[Center] );
if ( A[Left] > A[Right] )
Swap( &A[Left], &A[Right] );
if ( A[Center] > A[Right] )
Swap( &A[Center], &A[Right] );
//此时 A[Left] <= A[Center] <= A[Right]
Swap( &A[Center], &A[Right - 1] ); //将基准Pivot藏到右边
//只需考虑A[Left + 1] ... A[Right - 2]
return A[Right - 1];
}
void Qsort ( ElementType A[], int Left, int Right ) {
//核心递归函数
int Pivot, Cutoff = 100, Low, High; //Cutoff = 0会出错,如果最后只剩1个元素,做快排会数组越界
if ( Cutoff <= Right - Left ) { //如果序列元素充分过,进入快排
Pivot = Median3( A, Left, Right ); //选基准
Low = Left; High = Right -1;
while (1) { //将序列中比基准小的移到基准左边,大的移到右边
while ( A[++Low] < Pivot ) ;
while ( A[--High] > Pivot ) ;
if ( Low < High ) Swap( &A[Low], &A[High] );
else break;
}
Swap( &A[Low], &A[Right - 1] ); //将基准换到正确的位置
Qsort( A, Left, Low - 1 ); //递归解决左边
Qsort( A, Low + 1, Right ); //递归解决右边
}
else Insertion_Sort( A + Left, Right - Left + 1 ); //元素太少,用简单排序
}
void Quick_Sort ( ElementType A[], int N ) {
//统一接口
Qsort( A, 0, N - 1 );
}
//基数排序-次位优先-只能排自然数(有负数需分类讨论)
//假设元素最多有MaxDigit个关键字,基数全是同样的Radix
#define MaxDigit 10
#define Radix 10
//桶元素结点
typedef struct Node *PtrToNode;
struct Node {
int key;
PtrToNode next;
};
//桶头结点
struct HeadNode {
PtrToNode head, tail;
};
typedef struct HeadNode Bucket;
int GetDigit ( int X, int D ) {
int d, i;
for ( i = 1; i <= D; i++ ) {
d = X % Radix;
X /= Radix;
}
return d;
}
void LSDdixSort ( ElementType A[], int N ) {
//基数排序-次位优先
int D, Di, i;
Bucket B[Radix];
PtrToNode tmp, p, List = NULL;
for ( i = 0; i < Radix; i++ ) //初始化每个桶为空链表
B[i].head = B[i].tail = NULL;
for ( i = 0; i < N; i++ ) { //将原始序列逆序存入初始链表List
tmp = (PtrToNode)malloc(sizeof(struct Node));
tmp->key = A[i];
tmp->next = List;
List = tmp;
}
//下面开始排序
for ( D = 1; D <= MaxDigit; D++ ) { //对数据的每一位循环处理
//下面是分配过程
p = List;
while (p) {
Di = GetDigit(p->key, D); //获得当前元素的当前位数字
//从List中摘除
tmp = p; p = p->next;
//插入B[Di]号桶尾
tmp->next = NULL;
if ( B[Di].head == NULL )
B[Di].head = B[Di].tail = tmp;
else {
B[Di].tail->next = tmp;
B[Di].tail = tmp;
}
}
//下面是收集过程
List = NULL;
for ( Di = Radix - 1; Di >= 0; Di-- ) //将每个桶的元素顺序收集入List
if ( B[Di].head ) { //如果桶不为空
//整桶插入List表头
B[Di].tail->next = List;
List = B[Di].head;
B[Di].head = B[Di].tail = NULL; //清空桶
}
}
//将List倒入A[]并释放空间
for ( i = 0; i < N; i++ ) {
tmp = List;
List = List->next;
A[i] = tmp->key;
free(tmp);
}
}
//基数排序-主位优先
void MSD ( ElementType A[], int L, int R, int D ) {
//核心递归函数:对A[L]...A[R]的第D位数进行排序
int Di, i ,j;
Bucket B[Radix];
PtrToNode tmp, p, List = NULL;
if ( D == 0 )
return ; //递归终止条件
for ( i = 0; i < Radix; i++ ) //初始化每个桶为空链表
B[i].head = B[i].tail = NULL;
for ( i = L; i <= R; i++ ) { //将原始序列逆序存入初始链表List(不同)
tmp = (PtrToNode)malloc(sizeof(struct Node));
tmp->key = A[i];
tmp->next = List;
List = tmp;
}
//下面是分配过程
p = List;
while (p) {
Di = GetDigit(p->key, D); //获得当前元素的当前位数字
//从List中摘除
tmp = p; p = p->next;
//插入B[Di]号桶(与LSD不同)
if ( B[Di].head == NULL )
B[Di].tail = tmp;
tmp->next = B[Di].head;
B[Di].head = tmp;
}
//下面是收集过程(不同)
i = j = L; //i, j记录当前要处理的A[]的左右端下标
for ( Di = 0; Di < Radix; Di++ ) {
if ( B[Di].head ) {//将非空的桶整桶倒入A[],递归排序
p = B[Di].head;
while (p) {
tmp = p;
p = p->next;
A[j++] = tmp->key;
free(tmp);
}
//递归对该桶数据排序,位数减1
MSD( A, i, j - 1, D - 1 );
i = j; //为下一个桶对应的A[]左端
}
}
}
void MSDRadixSort ( ElementType A[], int N ) {
//统一接口
MSD( A, 0, N - 1, MaxDigit );
}
//桶排序
#define BucketNumber 100
void Bucket_Sort ( ElementType A[], int N ) {
int i;
PtrToNode tmp, p, List = NULL;
Bucket B[BucketNumber];
for ( i = 0; i < BucketNumber; i++ ) //初始化每个桶为空链表
B[i].head = B[i].tail = NULL;
for ( i = 0; i < N; i++ ) { //将原始序列逆序存入初始链表List
tmp = (PtrToNode)malloc(sizeof(struct Node));
tmp->key = A[i];
tmp->next = List;
List = tmp;
}
//分配
p = List;
while (p) {
//从List中摘除
tmp = p; p = p->next;
//插入B[tmp->key]号桶尾
if ( B[tmp->key].head == NULL )
B[tmp->key].tail = tmp;
tmp->next = B[tmp->key].head;
B[tmp->key].head = tmp;
}
//收集
List = NULL;
for( i = BucketNumber - 1; i >= 0 ; i-- ) //从小到大排序
if ( B[i].head ) { //如果桶不为空
//整桶插入List表头
B[i].tail->next = List;
List = B[i].head;
B[i].head = B[i].tail = NULL; //清空桶
}
//将List倒入A[]并释放空间
for ( i = 0; i < N; i++ ) {
tmp = List;
List = List->next;
A[i] = tmp->key;
free(tmp);
}
}
int main () {
ElementType A[MAX];
int N;
scanf("%d", &N);
for(int i = 0; i < N; i++)
scanf("%ld", &A[i]);
//qsort( A, N, sizeof(ElementType), compare );
//Quick_Sort( A, N );
//LSDdixSort( A, N );
//MSDRadixSort( A, N );
Bucket_Sort( A, N );
printf("%d", A[0]);
for(int i = 1; i < N; i++)
printf(" %d", A[i]);
/*int N;
scanf("%d", &N);
for ( int i = 0; i < N; i++ )
scanf("%ld %ld", &A[i].key1, &A[i].key2);
qsort( A, N, sizeof(struct Node), compare2keys );
for ( int i = 0; i < N; i++ )
printf("%ld %ld\n", A[i].key1, A[i].key2);*/
system("pause");
return 0;
}
快速排序和基数排序
最新推荐文章于 2021-12-13 20:36:12 发布