基本排序系列之基数排序

基数排序

一、基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

其实现原理:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,
数列就变成一个有序序列。

二、具体操作:此排序的真正实现是通过队列的装置,先进先出的原理,通过把个位,十位,百位,等其他进制也一样,放到不同的队列中(俗称桶)再按照先进先出的原理得到新的序列,在通过百位将其重新入桶回收等操作有获取新的序列,按此以来得到最终的序列便是排序好的序列。

三、基数排序不同于其他排序,一般我们见到的排序都是通过比较得到的,快排,归并都不例外,这个排序对于整数有特别好的效率而且也是一种稳定的排序。对于基数排序算法中要m次的n个节点来存放临时元素所以给予链式队列的基数排序,其算法复杂度为O(n)。对于顺序队列和链式队列基数排序算法的时间复杂度相同也为O(2mn)。

接下来我们以十进制:

500,342,45,666,006,841,429,134,78,264为例:

第一次:

0 500
1 841
2 342
3
4 134 264
5 45
6 666 006
7
8 78
9 429

得到:500 841  342  134 264  45  666   006  78  429

第二次:

0 500 006
1
2 429
3 134
4 841 342     45
5
6 264 666
7 78
8
9

得到: 500  006   429   134  841  342  45   264   666   78

第三次:

0 006   45    78
1 134
2 264
3 342
4 429   
5 500
6 666
7
8 841
9

得到:006   45   78  134  264  342   429   500   666   841

这就得到了排序。

排序段代码:

/**
*基数排序的操作方法实现Radix_sort()
*SNode  *S 用来接收tub的地址
*@param int a[] 表示接受要排序的数组
*@param int length 表示该要排序的数组的长度
*@param int d  表示进制,这里假设是十进制
*@param int m 表示的是要比较的数的最大的位数
*@return 无
*/
void Radix_sort(DataType a[],int length ,int d,int m){
	     int power = 1,k;
		 //用来计算装桶的次数
		 int count= 1;
	    //把d个队列定义成动态数组
	     Queue *tub ;
		 tub  = (Queue *)malloc(sizeof(Queue)*d);
		 //对每一个队列进行初始化
		 cout<<"_____________________________________________"<<endl;
		 for(int i = 0;i <d;i++){
		      QueueInitiate(&tub[i]);
		 }
		 cout<<"_____________________________________________"<<endl;
		 //对桶内进行m此的放入和收回
		 for(int i = 0;i <m;i++){
			 if(i == 0){
			       power = 1;
			 }else{
			       power *=d;
			 }
		 //将数据元素按照关键字第k位的数值放到相应的队列中
		 cout<<"第"<<count<<"次装桶过程!"<<endl;
		 cout<<"_____________________________________________"<<endl;
		 for(int j = 0;j <length ;j++){
			 //在接收了传进来的进制和位数后我们必须对每一个数进行处理
		      k =a[j]/power-(a[j]/(power *d))*d;
			  QueueAppend(&tub[k],a[j]);

		 }
		 cout<<"_____________________________________________"<<endl;
		 //顺序的回收队列中的数据元素到a的数组中
		 k = 0;
		 cout<<"第"<<count<<"次回收装桶后的元素!"<<endl;
		 cout<<"_____________________________________________"<<endl;
		 for(int j = 0;j < d;j++){
			 while( QueueNotEmpty(tub[j])!=0){
			        QueueDelete(&tub[j],&a[k]);
					cout<<"回收装桶元素成功!"<<endl;
					k++;
			 }
			/* for(int i = 0;i <d ;i++){
			       cout<<">>>>>第"<<i+1<<"个元素:"<<a[i]<<endl;
			 }*/
			  if(j==d){
		          cout<<"回收装桶元素成功!"<<endl;
		      }
		 }
		 count++;
		 cout<<"_____________________________________________"<<endl;
		 }
}

插入段代码:

<span style="font-size:18px;">/**
*队列的插入,即桶的数据的装桶操作
*@param Queue *Q用来接收传进来的地址
*@param int num 表示要入桶的数
*return Queue  *
*/
Queue *QueueAppend(Queue *Q,int num){
	    /**
	    *这里我们首先得为rear ,front申请空间并初始化
		*
		*/
	   /* Queue *Q;
		*判断有无空间可申请,并是否申请成功
		*if(Q != NULL){
        *     free(Q);
        *	 Q =NULL;
        *}
	    *Q = (Queue *)malloc(sizeof(Queue));
		*if(Q !=NULL){
		*    cout<<"Q-头节点和尾节点申请空间成功!"<<endl;
		*}else{
        *    cout<<"内存空间不足!"<<endl;
		*	 return ;
	    *}
		*初始化头节点和尾节点
		*Q->rear = NULL;
        *Q->front = NULL;
		*/

	   /**
	   *这里判断R是否为空并释放空间
	   *然后对其申请空间按
	   */
	    SNode *p =NULL;
	    if(p != NULL){
             free(p);
        	 p =NULL;
        }
	    p = (SNode *)malloc(sizeof(SNode));
		if(p !=NULL){
		     cout<<"申请空间成功!"<<endl;
		}else{
             cout<<"内存空间不足!"<<endl;
			 return Q;
	    }

        p->data = num;//这里得放其位数如个位,十位,百位
        p->next = NULL;//到此已经成功的创建了一个新的节点
		/**
	     *将新的节点插入队列的末尾
		 *
		 */
		 if(Q->rear != NULL){
			    Q->rear->next = p;
				Q->rear = p;
		  }
		 if(Q->front == NULL){
			    Q->rear = p;
				Q->front = p;
		 }
		 cout<<"装桶成功!"<<endl;
         return Q;

}</span>

回收段代码:

/**
*链式队列中的元素的删除
*@param Queue *q 用来接收要回收的元素的地址
*@param DataType *d  用来存储储存收回的元素
*@return int
*/
 int QueueDelete(Queue	*q,DataType	*d){
 	SNode *p;
    /**
	 *判断内存中是否有数据,有就输出,没有返回0
	 *
	 */
	if(q->front == NULL){
			cout<<"此时队列中无元素出列!"<<endl;
			return 0;
	}else{
		*d = q->front->data;
		 p = q->front;
		 q->front= q->front->next;
	}
    if(q->front == NULL){
 	     q->rear = NULL;
 	}
	free(p);//释放节点内存空间
    return 1;
} 

全部代码:

/**
*基数排序原理就是利用桶也就是队列来排序的
*@author 菜鸟
*@version 2014.6.15
*/

#include <iostream>
#include <windows.h>
#include <malloc.h>
#define  MaxSize 100
using namespace std;
typedef int DataType;
//定义节点用来做链式队列
typedef struct Node{
	 DataType data;
	 struct Node *next;

}SNode;

//定义一个结构体将队列的头尾指针放在一起
typedef struct{
       SNode *rear;
       SNode *front;
}Queue;
//初始化头节点与尾节点
void QueueInitiate(Queue *q){
         q->rear = NULL;
         q->front = NULL;
		 cout<<"成功初始化!"<<endl;
}
 //判断队列非空
int QueueNotEmpty(Queue q){
		if(q.front== NULL){
				return 0;
       	}else {
       		    return 1;
	    }
}
/**
*队列的插入,即桶的数据的装桶操作
*@param Queue *Q用来接收传进来的地址
*@param int num 表示要入桶的数
*return Queue  *
*/
Queue *QueueAppend(Queue *Q,int num){
	    /**
	    *这里我们首先得为rear ,front申请空间并初始化
		*
		*/
	   /* Queue *Q;
		*判断有无空间可申请,并是否申请成功
		*if(Q != NULL){
        *     free(Q);
        *	 Q =NULL;
        *}
	    *Q = (Queue *)malloc(sizeof(Queue));
		*if(Q !=NULL){
		*    cout<<"Q-头节点和尾节点申请空间成功!"<<endl;
		*}else{
        *    cout<<"内存空间不足!"<<endl;
		*	 return ;
	    *}
		*初始化头节点和尾节点
		*Q->rear = NULL;
        *Q->front = NULL;
		*/

	   /**
	   *这里判断R是否为空并释放空间
	   *然后对其申请空间按
	   */
	    SNode *p =NULL;
	    if(p != NULL){
             free(p);
        	 p =NULL;
        }
	    p = (SNode *)malloc(sizeof(SNode));
		if(p !=NULL){
		     cout<<"申请空间成功!"<<endl;
		}else{
             cout<<"内存空间不足!"<<endl;
			 return Q;
	    }

        p->data = num;//这里得放其位数如个位,十位,百位
        p->next = NULL;//到此已经成功的创建了一个新的节点
		/**
	     *将新的节点插入队列的末尾
		 *
		 */
		 if(Q->rear != NULL){
			    Q->rear->next = p;
				Q->rear = p;
		  }
		 if(Q->front == NULL){
			    Q->rear = p;
				Q->front = p;
		 }
		 cout<<"装桶成功!"<<endl;
         return Q;

}
/**
*链式队列中的元素的删除
*@param Queue *q 用来接收要回收的元素的地址
*@param DataType *d  用来存储储存收回的元素
*@return int
*/
 int QueueDelete(Queue	*q,DataType	*d){
 	SNode *p;
    /**
	 *判断内存中是否有数据,有就输出,没有返回0
	 *
	 */
	if(q->front == NULL){
			cout<<"此时队列中无元素出列!"<<endl;
			return 0;
	}else{
		*d = q->front->data;
		 p = q->front;
		 q->front= q->front->next;
	}
    if(q->front == NULL){
 	     q->rear = NULL;
 	}
	free(p);//释放节点内存空间
    return 1;
}
/**
 *输出函数
 *@param int a[]用来接收数组
 *@param int n  表示数组的长度
 *@return 无
 */
 void out_put(int a[],int n){
	 cout<<"_____________________________________________"<<endl;
	 for(int i = 0;i < n;i++){
	      cout<<"第"<<i+1<<"个元素:"<<a[i]<<endl;
	 }
	 cout<<"_____________________________________________"<<endl;
 }
/**
*基数排序的操作方法实现Radix_sort()
*SNode  *S 用来接收tub的地址
*@param int a[] 表示接受要排序的数组
*@param int length 表示该要排序的数组的长度
*@param int d  表示进制,这里假设是十进制
*@param int m 表示的是要比较的数的最大的位数
*@return 无
*/
void Radix_sort(DataType a[],int length ,int d,int m){
	     int power = 1,k;
		 //用来计算装桶的次数
		 int count= 1;
	    //把d个队列定义成动态数组
	     Queue *tub ;
		 tub  = (Queue *)malloc(sizeof(Queue)*d);
		 //对每一个队列进行初始化
		 cout<<"_____________________________________________"<<endl;
		 for(int i = 0;i <d;i++){
		      QueueInitiate(&tub[i]);
		 }
		 cout<<"_____________________________________________"<<endl;
		 //对桶内进行m此的放入和收回
		 for(int i = 0;i <m;i++){
			 if(i == 0){
			       power = 1;
			 }else{
			       power *=d;
			 }
		 //将数据元素按照关键字第k位的数值放到相应的队列中
		 cout<<"第"<<count<<"次装桶过程!"<<endl;
		 cout<<"_____________________________________________"<<endl;
		 for(int j = 0;j <length ;j++){
			 //在接收了传进来的进制和位数后我们必须对每一个数进行处理
		      k =a[j]/power-(a[j]/(power *d))*d;
			  QueueAppend(&tub[k],a[j]);

		 }
		 cout<<"_____________________________________________"<<endl;
		 //顺序的回收队列中的数据元素到a的数组中
		 k = 0;
		 cout<<"第"<<count<<"次回收装桶后的元素!"<<endl;
		 cout<<"_____________________________________________"<<endl;
		 for(int j = 0;j < d;j++){
			 while( QueueNotEmpty(tub[j])!=0){
			        QueueDelete(&tub[j],&a[k]);
					cout<<"回收装桶元素成功!"<<endl;
					k++;
			 }
			/* for(int i = 0;i <d ;i++){
			       cout<<">>>>>第"<<i+1<<"个元素:"<<a[i]<<endl;
			 }*/
			  if(j==d){
		          cout<<"回收装桶元素成功!"<<endl;
		      }
		 }
		 count++;
		 cout<<"_____________________________________________"<<endl;
		 }
}

int main(){
	  int a[10]={500,342,45,666,006,841,429,134,78,264};
	  cout<<"未排序的元素:"<<endl;
	  out_put(a,10);
	  Radix_sort(a,10,10,3);
	  cout<<"经排序后的元素:"<<endl;
	  out_put(a,10);
	  system("PAUSE");
	  return 1;
}

代码经验证过!

基本排序系列之基数排序,布布扣,bubuko.com

时间: 2024-10-14 10:27:12

基本排序系列之基数排序的相关文章

16. 蛤蟆的数据结构进阶十六排序实现之基数排序

16. 蛤蟆的数据结构进阶十六排序实现之基数排序 本篇名言:"社会犹如一条船 ,每人都要有掌舵的准备.--易卜生" 我们来看下基数排序. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47760601 1.  基数排序 基数排序(radix sort)属于"分配式排序"(distributionsort),又称"桶子法"(bucket sort)或bin sort,顾名思义,

基本排序系列之计数排序

简述计数排序 看了好多别人写的计数排序,看了好久都没看懂,弄了好久最后发现这么简单居然花了几个小时,所以在这里写上,希望和我一样的初学者不会再绕弯路. 一.简述计数排序的思想: 设被排序的数组为A,排序后存储到B,C为临时数组.所谓计数,首先是通过一个数组C[i]计算大小等于i的元素个数,此过程只需要一次循环遍历就可以:在此基础上,计算小于或者等于i的元素个数,也是一重循环就完成.下一步是关键:逆序循环,从length[A]到1,将A[i]放到B中第C[A[i]]个位置上.原理是:C[A[i]]

排序系列之——冒泡排序、插入排序、选择排序

排序之——冒泡排序: 基本思想:假设待排序表长为N,从后往前(或者从前往后)两两比较相邻元素的值,若为逆序(arr[i-1]>arr[i]),则交换他们,直到序列比较完.这时一趟冒泡. 代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <time.h> 5 #define N 20 6 7 void print_Arr(int *arr,

第八章 线性时间排序 8.3 基数排序

package chap08_Linear_Time_Sort; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; public class CopyOfSortAlgorithms { /** * 基数排序 * * @param n * @param digit */ static void radixSort(int[] n, int digit) { int[] b = new

排序算法之基数排序

概述 首先从多排序码排序开始介绍基数排序.以扑克牌排序为例.每张扑克牌有两个"排序码":花色和面值.其有序关系为: 花色:?<?<?<? 面值:2<3<4<5<6<7<8<9<10<J<Q<K<A 如果把所有扑克牌排成以下次序: ?2,-,?A,?2,-,?A,?2,-,?A,?2,-,?A 这就是多排序码排序.排序后形成的有序序列叫做字典有序序列. 一般情况下,假定有一个n个元素的序列{V0,V

经典排序算法之基数排序(C语言版)

排序算法之基数排序的C语言实现. #include "math.h" #include "stdio.h" /* * 基数排序 2016-04-18 23:43:49 * 基数排序的思想:1.求出数组中最大的元素. *   2.求出最大元素是几位数.设为i位. *   3.对所有的数进行i轮排序.首先排个位,然后在十位,然后百位...... *   4.每一轮的排位都需要分桶,桶是有顺序的,然后在把桶里的数按顺序放入原来的数组中. *   5.直到i轮排序结束后,数

C# 插入排序 冒泡排序 选择排序 高速排序 堆排序 归并排序 基数排序 希尔排序

以下列出了数据结构与算法的八种基本排序:插入排序 冒泡排序 选择排序 高速排序 堆排序 归并排序 基数排序 希尔排序,然后是測试的样例.代码位置:http://download.csdn.net/detail/luozuolincool/8040027 排序类: public class Sortings { //插入排序 public void insertSort(int[] array) { int temp = 0; int index = 0; for (int i = 0; i <

八大排序算法之基数排序

设计思想 它是根据关键字中各位的值,通过对排序的N个元素进行若干趟"分配"与"收集"来实现排序的.它不要比较关键字的大小. 假设:R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100} 任何一个阿拉伯数,它的各个位数上的基数都是以0~9来表示的.所以我们不妨把0~9视为10个桶. 我们先根据序列的个位数的数字来进行分类,将其分到指定的桶中.例如:R[0] = 50,个位数上是0,将这个数存入编号为0的桶中. 分类后,我们在从各个桶中

排序七:基数排序

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace RadixSort 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 int[] arr = new int[10]; 14 Rand