快速排序和基数排序

9 篇文章 0 订阅

承接 09-排序1 排序 (25分)

#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;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值