排序算法(带完整注释)

学习排序算法时写的,采用C实现,缺陷在于没有对算法复杂度和时间运行进行分析~不过代码很用心注释了的,欢迎指正。

//排序算法
#include <stdio.h>
#include <stdlib.h>
#include <time.h> 
int main()
{
	int n,i,c,Way;                                                                //(选10长度的序列报个小错误。。。,应该不是函数内部问题
	void Bubblingsort(int a[],int n);//冒泡排序
	void Insertsort(int a[],int n);//直接插入排序  
    void Selectsort(int a[],int n);//选择排序
 	int  Mergesort(int a[],int head,int tail);//归并排序
 	int  Sort(int a[],int head, int mid,int tail); //归并排序中排序函数
 	void Quicksort(int a[],int head,int tail);//快速排序
 	void CountSort(int a[],int len,int c);//计数排序  
 	void RadixSort(int a[], int n);//基数排序
 	void Sort(int a[],int n,int d);//基数排序中排序函数
 	int  GetDValue(int value, int d);//基数排序中取位函数
 	void Hillsort(int a[],int head,int tail);//希尔排序 
 	void print_arry(int *a,int n);//打印函数
 	void choose(int arr[],int n,int i,int c);
	
    printf ("1、冒泡排序\n");
    printf ("2、直接插入排序\n");
    printf ("3、选择排序\n");
    printf ("4、归并排序\n");
    printf ("5、快速排序\n");
    printf ("6、计数排序\n");
    printf ("7、基数排序\n");
    printf ("8、希尔排序\n");

    printf ("请选取需要测试的排序方法 Way="); 
    scanf ("%d", &Way); 
    if(Way>8&&Way<1)
   	 {
	    printf("无法进行排序\n");
		exit(0);
	 } 
	printf ("所取排序随机数个数 n=");   
    scanf ("%d", &n); 
    printf ("测试取整数范围 c=");
    scanf ("%d", &c); 
    printf("\n");
    
    n=n-1;
    
    int *arr = (int *)malloc(sizeof(int) * n);  
    srand (time (0));  
    for (i = 0; i<=n; i++)  
      {  
        arr[i] = rand() % c;  
      } 
    printf ("随机生成数值为0~%d的数组...\n",c);  
    
    printf ("初始化数组: ");  
    print_arry(arr, n);  
	 
    printf ("排序后的数组:"); 

	    switch(Way)
			{
				case 1:
				Bubblingsort(arr,n);//冒泡排序 
				break;
				case 2:
				Insertsort(arr,n);//直接插入排序
				break;
				case 3:
				Selectsort(arr,n);//选择排序
				break;
				case 4:
 				Mergesort(arr,0,n);//归并排序
				break;
				case 5:
				Quicksort(arr,0,n); //快速排序 
				break;
				case 6:
				CountSort(arr,n,c);//计数排序 
				break;
				case 7:
				RadixSort (arr,n);//基数排序
				break;
				case 8:
				Hillsort(arr,0,n); //希尔排序 
				break;
			    default:
     		    break;
			}

    print_arry(arr, n);  
    return 0; 
    system ("pause");
}

 
//冒泡排序:
  void Bubblingsort(int a[],int n)
 {	
            int i,j,t;
 	for(i=0;i<=n;i++)
	  { 
			for(j=0;j<=n-1;j++)
			{
				if(a[j]>a[j+1])
			    {
				  t=a[j];
			      a[j]=a[j+1];
			      a[j+1]=t; 
			    }
				
			}
	  }
 	
  } 
//直接插入排序:
 void  Insertsort(int a[],int n)     	    	//1、传入数组a[]和其长度n 
{
	int i,t,m; 
	for(i=1;i<=n;i++)
	  { 
	        t=a[i];  
				                           		//2、以t=a[i]记录待插入的值 
			for(m=i;m>0;m--)                    //3、开始往前循环,当未搜索到比a[i]小的值a[m-1],每一次通过 a[m]=a[m-1]将a[m-1]向后移位,
								                //当搜索到比a[i]小的值a[m-1],那么m的值即应为a[i]在已排序列中的正确位置。 
			{   
				if(t<a[m-1])
			    { 			      
			      a[m]=a[m-1];   				     
			    }
			    else			    			       
			        break;							       			
			}		
				a[m]=t;		            		//4、找到m值,即可将记录好的t值赋予a[m],完成一次插入	
	  }
}
//选择排序:每一趟排序,从未排序中最小值与未排序的第一个数字交换位置。 
  void Selectsort(int a[],int n)
 {
 	int i,d,m,t;
	for(i=0;i<=n;i++)            
      { 
	        d=i;                        		 //1、通过d=i记录i的值。                  
			for(m=n;m>i;m--)          			 //2、通过遍历,在未排序的序列中,通过比较找出最小值并使d等于序列中最小值的下标。 
			{   
				if(a[d]>a[m])
			    { 			      
			      d=m;  		  				     
			    }
			    							       			
			}	
			    t=a[i];
				a[i]=a[d];	                      //3、通过交换位置,使最小值换到未排序序列首位。 
				a[d]=t;	
      } 
 	
  } 
 //归并排序:
 int  Sort(int a[],int head, int mid,int tail)    //1、传递待排序列a、序列a的起始下标head、分段中点mid、 末尾下标tail 
 {  int i=head,j=mid+1,k=0;
    int temp[1000]={0};                           //2、暂设临时数组(最好用申请内存malloc合理分配空间,此处仅供测验) 
    for(i=head,j=mid+1,k=head;k<=tail;)           //3、待排序列被mid分为两段,i、j分别为一段的起始点,开始排序 
    {
    	
    	if(i==mid+1)                               //4、当i=mid+1,左段已全部放到临时数组temp,此时只需从j后面的全放到临时数组temp 
		{
			temp[k]=a[j];
			j++;
			k++;	
		}
		
		if(j==tail+1)                               // 5、同上一注释 
		{
			temp[k]=a[i];
			k++;
			i++;
		}
		
    	if(i<=mid&&j<=tail)                         //6、(排序第一步必从这里开始时)此时条件下, 比较a[i]的a[j]的大小,小的便放到临时数组temp[],然后下标自加 1 ,程序循环,完成序列a[]的排序。  
    	{
    		
    		if(a[i]<a[j])
    		{
    			temp[k]=a[i]; 
    			k++;
    			i++;		  			
			} 
			else
			{
			    temp[k]=a[j]; 
			    k++;
			    j++;
			} 		  		
		}
	
	}
	for(i=head;i<=tail;i++)
	a[i]=temp[i]; 

}

int Mergesort(int a[],int head,int tail)
  { 
    int mid;
  		mid=(tail+head)/2; 
	if(mid>head)                                   //7、当(mid>head)>0,说明此时序列只有一个数,此时无需进行序列排序 
	   {    
  		mid=(tail+head)/2;                        
  		Mergesort(a,head,mid);                    
  		Mergesort(a,mid+1,tail);                   //9、进行递归(通过观察程序可以发现,此处将一直往下一直找到最小的序列,即两个数字的时候,才会退出if,进行Sort函数排序,排好序,然后两个排序好的两个数字(一共四个),以此类推。 
		}                                          //可以看出归并排序是从最底层往上排。 
     	Sort(a,head,mid,tail);
		
}
  	
//快速排序:
void Quicksort(int a[],int head,int tail)                    //1、传入待排序数组a[],数组a[]首个数值下标head,末尾数值下标tail。 
 {  int i=head+1,j=tail,k=0,key,t=0;
    key=head;     											 //2、令key等于数组首下标。 
    for(k=0;k<tail-head;)                                 	 //3、以k从0开始循环,循环数组长度tail-head次。 
    { 
    	if(key<=i)                                           //4、当key<=i,说明key需要从j往前搜索。 
    	{
    		if(a[key]>a[j])									 //5、从j开始搜索时,当满足a[key]>a[j],那么互换位置,然后令key=j;此时完成一次搜索,需k++。 
    		{   
				t=a[key];
    			a[key]=a[j];
    			a[j]=t;
    			key=j;
    			k++;
			}
			else											 //6、不满足条件时,令j--,往前继续搜索,此时也完成一次搜索,需k++。 
			{
				j--;
				k++;
			}
	  }
    	if(key>i)                                            //7、key>i,说明key需要从i往后搜索。
		{
			if(a[key]<a[i])									 //8、从i开始搜索时,当满足a[key]<a[j],那么互换位置,然后令key=i;此时完成一次搜索,需k++
			{
				t=a[key];
    			a[key]=a[i];
    			a[i]=t;
    			key=i;
    			k++;        
			}	  
			else											 //9、不满足条件时,令i++,往后继续搜索,此时也完成一次搜索,需k++。 
			{
				i++;
				k++;		  
			}
		}		
   	}                                                        //(程序每一次搜索都会k++,当判断k在刚好下一刻大于序列长度时,i==j。循环结束。 

if((key-1)>0)                                                //10、当(key-1)>0,递归调用qupicksort函数,当 (key-1)<0,说明此时序列a[0]~a[key]只有两个数,此时停止递归。 
   Quicksort(a,0,key-1);
if(key+1<tail)												 //11、当key+1<tail,递归调用qupicksort函数,理由参考注释10 (判断条件我们可以从排三个数去想) 
   Quicksort(a,key+1,tail);									  
}
//计数排序:
int CountSort(int a[],int len,int c)
 {
    int *Count=	NULL; 
    Count = (int*)malloc(sizeof(int)*c);
    int *Sort=NULL;
	Sort = (int*)malloc(sizeof(int)*len);
    for(int i=0;i<=c;i++)
      {
    	Count[i]=0;                 //1、初始化计数数组 
      }
	
	for(int i = 0;i<=len;i++)      //2、统计i的次数
      {
      
     	Count[a[i]]++;  
      } 
	
	for(int i = 1; i<c; i++)       //3、对所有的计数累加,这一步目的是为了让Count的值和放排序的数组Sort的下标建立联系。 
      {
   	    Count[i] += Count[i-1];
	  } 
    
    for(int i = len; i>=0; i--)   //4、每一次,我们以a[i]为Count[]下标,取得Count[]的值 ,然后让Count[]-1的值作为Sort[]的下标, 
      {                           // 再给对应的Sort[]赋a[i]的值,此时,a[i]的值便会储存到Sort正确的序列位置。 排序完毕。 
        Sort[Count[a[i]]-1] = a[i]; 
        Count[a[i]]--;    
      } 

	for(int i=len;i>=0;i--) 
	  {
		a[i]=Sort[i]; 

	  } 
        
         free(Count);   
		 free(Sort); 
    
     
  }
  
//基数排序:
void RadixSort(int a[], int n)        // 1、调用排序函数,每一次移位,从低到高进行排序。最后得到最终的正确序列 
{  
    int i,WIDTH=4;                
    void Sort(int a[], int n, int d);  
    for (i = 0; i < WIDTH; i++) 
	  {  
        Sort(a, n, i);  
      }  
}  

 void Sort(int a[],int n,int d)       // 2、 传递进待排序数组a[]、 数组长度、需要排序的基数位 
{  
    int i, j, x,MAXK=10, k[MAXK] = {0};  
    int *ip = (int *)malloc(n * sizeof (int));  
    int *bp = (int *)malloc(n * sizeof(int)); 
    int GetDValue(int value, int d); 
    for (i = 0; i <=n; i++)            //3、调用GetDValue,取得数组a[]的值的第d位数字,存入数组k[i]中 
	  {  
        ip[i] = GetDValue(a[i], d);  
        k[ip[i]]++;  
      }  
  
    for (j = 1; j < MAXK; j++)   		//4、对数组k[]进行累加 
	  {       
        k[j] +=  k[j-1];  
      }  
  
    for (i = n; i >= 0; i--) 			 // 5、每一次,我们以ip[i]为k[]下标,取得k[]的值 ,然后让k[]-1的值作为bp[]的下标, 
      {                                  // 再给对应的bp[]赋a[i]的值,此时,ip[i]的值便会储存到bp正确的序列位置。 排序完毕。  
        bp[k[ip[i]] - 1] = a[i];  
        k[ip[i]]--;  
      }  
  
    for (i = 0; i <=n; i++) 
	  {  
        a[i] = bp[i];                     
      }  
  
    free(ip);  
    free(bp);
} 
int GetDValue(int value, int d)          //获取一个数第d位数的值,位数索引从0开始
{   
    int MAXK=10; 
    for (;d > 0 && value > 0; d--) 
	  {  
        value = value / MAXK;  
      }  
    return value % MAXK;  
}  
//希尔排序,详情参照归并递归思想,和直接插入排序注释。
 void Hillsort(int a[],int head,int tail)   
{
	int mid;
	void Insertsort(int a[],int n);
	if((tail-head)>0)
	{
		mid=(tail+head)/2;
		Hillsort(a,head,mid);
		Hillsort(a,mid+1,tail);
	}
	Insertsort(a,tail);
}


 void print_arry(int *a,int n)  
{  
    int i;  
    for(i = 0; i<=n; i++)  
    {  
        printf("%d ", a[i]);  
    }  
    printf("\n");  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值