几类排序的思想及实现

1.插入排序

(1).直接插入排序
//直接插入排序,把第一个数看做是有序的,然后将后面的数不断插入到前面有序的数列
void insert_sort(int a[], int len)
{
 for(int i=1; i<len; i++)
 {
  int x=a[i];           //当前要插入的元素
  int j=i-1;
  while(j>=0 && x<a[j])       //与前面的元素进行比较
  {
   a[j+1]=a[j];            //元素前移
   j--;
  }
  a[j+1]=x;                  //将元素插入应该的位置
 }
}

(2).shell
//shell(希尔)排序,设置一个增量,然后将数组按增量分成几部分,将几部分进行插入排序,增量逐渐减小,最后为1的时候排序完成
void shell_sort(int a[], int len)
{
 for(int d=len/2; d>0; d/=2)        //增量初始化为数组长度的一半,每次增量都减半
 {
  for(int i=d; i<len; i++)       //将增量分成的各个数组进行插入排序
  {
   int x=a[i];
   int j=i-d;
   
   while(j>=0 && x<a[j])
   {
    a[j+d]=a[j];
    j-=d;
   }
   a[j+d]=x;
  }
 }

 


2.交换排序

(1).冒泡排序

//冒泡排序,比较相邻的两个数,将较大的数后移,每次冒泡后都将最大的数移到数组的最末尾
void bubble(int a[], int len)
{
 for(int i=0; i<len-1; i++)    
 {
  int j=i+1;

  if(a[j]<a[i])           //比较相邻的两个元素
   swap(a[j], a[i]);
 }
}

void bubble_sort(int a[], int len)
{
 for(int l=len; l>0; l--)      //逐渐减小要冒泡的范围
  bubble(a,l);
}

 

//及时终止的冒泡排序
void bubble_sort(int a[], int len)
{
 for(int l=len; l>0; l--)      //逐渐减小要冒泡的范围
 {
  bool changed=false;

  for(int i=0; i<len-1; i++)    
  {
   int j=i+1;

   if(a[j]<a[i])           //比较相邻的两个元素
   {
    swap(a[j], a[i]);
    changed=true;          //当有元素交换时,changed设置为真
   }
  }

  if(!changed)     //当数组前一次冒泡没有变化时,说明排序已经完成
   break;
 }
}


(2).快速排序
void quick_sort(int a[], int low, int high)       //low为要排序的初始下标,high为要排序的最大下标
{
 int i, j, pivot;

 if(low<high)
 {
  pivot=a[low];      //将数组的第一个数设为基点数
  i=low;
  j=high;

  while(i<j)
  {
   //先从数组后面开始往前寻找比基点小的数
   while(j>i && a[j]>=pivot)
    j--;
   //将小的数前移
   if(j>i)
    a[i++]=a[j];

   //从数组前面开始寻找比基点数大的数
   while(i<j && a[i]<=pivot)
    i++;
   if(j>i)
    a[j--]=a[i];
  }

  a[i]=pivot;
  quick_sort(a, low, i-1);             //对左边部分进行快速排序
  quick_sort(a, i+1, high);            //对右边部分进行快速排序
 }
}


3.选择排序

//在数组a[]的beg到end范围内寻找最小的数
int maxInArray(int a[], int beg, int end)        
{
 int index=beg;

 for(int i=beg+1; i<=end; i++)
 {
  if(a[i]<a[index])  
   index=i;
 }

 return index;
}


void select_sort(int a[], int len)
{
 for(int i=0; i<len; i++)
 {
  int index=maxInArray(a,i,len-1);        //找出数组内从i开始的最小的数

  swap(a[index], a[i]);                   //将数组内最小的数和第i个元素进行交换
 }
}

 


4.归并排序


思想是将数组两部分,然后两边采用归并排序形成两个有序数列,然后将两部分合并。

//将数组a[]的lbeg到rbeg-1的数和rbeg到rend的数合并
void Merge(int a[], int lbeg, int rbeg, int rend)    
{
 //临时数组,用保存合并后的有数组
 int *temp=new int[rend-lbeg+1];
 
 int i=lbeg, j=rbeg;
 int index=0;        //temp数组的下标

 //将两部分合并,但是当一部分全部插入到temp后,另一部分可能还剩余一些元素
 while(i<=rbeg-1 && j<=rend)
 {
  if(a[i]<=a[j])
   temp[index++]=a[i++];

  else
   temp[index++]=a[j++];
 }

 //如果是前半部分插入完毕,将后半部分剩余的元素插入到数组
 while(j<=rend)
  temp[index++]=a[j++];

 //如果后半部分插入完毕
 while(i<=rbeg-1)
  temp[index++]=a[i++];

 //将temp数组的元素复制到a[],将数组temp[0]~temp[rend-lbeg]拷贝到a[lbeg]~a[rend]
 int m=0;
 for(int k=lbeg; k<=rend; k++,m++)
  a[k]=temp[m];

 delete [] temp;
}

void merge_sort(int a[], int low, int high)
{
 if(low<high)
 {
  int mid=(low+high)/2;    //计算断裂点

     merge_sort(a, low, mid);   //将断裂点左侧的元素进行归并排序
     merge_sort(a, mid+1, high);    //将断裂点右侧的元素进行归并排序

     Merge(a,low,mid+1,high);       //将左右两侧的两个有序数列合并 
 }
}

 

 

5.基数排序

思想:个位排序,十位排序,一直到最高位


//返回数组内最大元素的下标
int max_in_array(int a[], int len)
{
 int index=0;

 for(int i=1; i<len; i++)
 {
  if(a[index]<a[i])
   index=i;
 }

 return a[index];
}

//返回一个数共有多少位
int num_bit(int num)
{
 int n=1;

 for(int i=num/10; i!=0; i/=10)
  n++;

 return n;
}

//返回num在index位上的数字
int num_at_index(int num, int index)
{
 for(int i=index; i>1; i--)
  num=num/10;

 return num%10;
}

//基数排序
void base_sort(int a[], int len)
{
 //首先找出数组最大的数,和最大数的位数
 int max_num=max_in_array(a, len);

 //一个大小为10的指针数组,用来当做箱子
 int *temp[10];

 
 //将箱子进行初始化
 for(int k=0; k<10; k++)
 {
  temp[k]=new int[len];       //每个箱子大小为len
 }


 //按位数排序,从个位开始一直到最高位
 for(int i=1; i<=num_bit(max_num); i++)
 {
  int count[10]={0,0,0,0,0,0,0,0,0,0};//用来记录每个箱子有多少个元素的数组

  //遍历数组a的各个元素,求出第i位的值
  for(int j=0; j<len; j++)
  {
   int number=num_at_index(a[j], i);

   //更行箱子的元素个数的计数
   count[number]++;

   //将元素放到对应的箱子里里面
   temp[number][count[number]-1]=a[j];
  }


  //将箱子里的元素放入到数组a[]
  int index=0;
  for(int m=0; m<10; m++)
  {
   for(int p=0; p<count[m]; p++)
    a[index++]=temp[m][p];
  }

 }

 //释放指针数组内各个指针指向的动态数组
 for(int u=0; u<10; u++)
 {
  delete [] temp[u];
 }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值