快速排序和基数排序

来源:互联网 发布:淘宝装修一键安装 编辑:程序博客网 时间:2024/06/08 00:35

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

#include <stdlib.h>#include <stdio.h>#define MAX 100005typedef 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++ ) { //将原始序列逆序存入初始链表Listtmp = (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-- )//将每个桶的元素顺序收集入Listif ( 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);}//递归对该桶数据排序,位数减1MSD( A, i, j - 1, D - 1 );i = j; //为下一个桶对应的A[]左端}}}void MSDRadixSort ( ElementType A[], int N ) {//统一接口MSD( A, 0, N - 1, MaxDigit );}//桶排序#define BucketNumber 100void 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++ ) { //将原始序列逆序存入初始链表Listtmp = (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 0
原创粉丝点击