排序学习(快速排序,归并排序,基数排序

本文深入探讨了三种主要的排序算法:快速排序、归并排序和基数排序。快速排序平均时间复杂度为O(NlogN),但最坏情况下达到O(N2)。归并排序保持稳定性,时间复杂度同样为O(NlogN),而空间复杂度为O(N)。基数排序则以O(N)的时间复杂度实现排序,特别适用于处理大量整数的排序问题。通过对这些算法的解析,读者能够更好地理解和应用它们。
摘要由CSDN通过智能技术生成

快速排序

平均时间复杂度 O(NlogN)
最差时间复杂度O(N2)**
不稳定


<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
 OTHER other;//此处可以放结构体来储存其他信息
};
//划分函数的实现
//以第一个元素为划分元素,将从high到low的一个区间划分两半
template<class KEY,class OTHER>
void divide(SET<KEY,OTHER>a[],int low,int high)
{
    //确定划分元素(此处默认首元素)
    SET<KEY,OTHER>k=a[low];//注意不要写成a[0]
    //这个划分函数的对象将是任意片段而非仅仅是原集合
    while(high>low)//终止标志是二者下标箭头重合,high=low也不用排序了,只有一个元素
    {
    //开始划分,low指向k位置,可以算作k位置为空
    //high指向末尾,从high开始与k比大小
    //注意集合中选取key值,k也是结构体要选取key
    while(high>low&&a[high].key>=k.key)high--;//high向前走直到找到一个比k小的元素停止
    if(high>low) a[low]=a[high];//high位置元素(结构体直接移动)移动到low位置,high位置空出来
    //向右移动low位置,找比k大的元素来填补high位置
    while(high>low&&a[low].key<=k.key)low++;
    if(high>low) a[high]=a[low];
    //时刻注意确认high>low情况
    //易错点:区分high/low是指向下标位置(始终顺序)的箭头,a[high].key与a[low].key是待排序的元素内容
    }
    //此时high=low
    a[low].key=low;
    return low;//返回中间位置
}

//快排的递归调用
template<class KEY,class OTHER>
void quickSort(SET<KEY,OTHER>a[],int low,int high)
{
   if(low>=high) return;//递归终止 
   int mid=divide(a,low,high);//相当于在表中确定了mid位置,之后mid不用排序
   quickSort(a,low,mid-1);
   quickSort(a,mid+1,high);//递归分成左右半边
}

归并排序

时间复杂度O(NlogN)
空间复杂度O(N)
稳定,注意等于号

#include <iostream>
using namespace std;
//定义一个集合
template<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
 OTHER other;//此处可以放结构体来储存其他信息
};
//归并两个已经排好序的相邻序列
//然后元素一一对比,找两序列中较小的放新序列中
//mid是第一个序列结尾+1与第二个序列开头
template<class KEY,class OTHER>
void merge(SET<KEY,OTHER>a[],int low,int mid,int high)
{ //新建一个数组用来存放归并后的序列
  SET<KEY,OTHER>*tmp=new SET<KEY,OTHER>[high-low+1];

  int i=left,j=mid,k=0;//两个放在开头的箭头,来表示归并到哪个位置
  //k专门看tmp走到哪里
  while(i<mid&&j<=high)
  {
      if(a[i].key<=a[j].key) tmp[k++]=a[i++];//重视等于号,这让此算法稳定
      else tmp[k++]=a[j++];
  }//其中一个走到了尽头
  //把还没走到尽头的依次填补到新序列中
  while(i<mid) tmp[k++]=a[i++];
  while(j<=high) tmp[k++]=a[j++];
  //tmp毕竟是函数中暂时的,把它元素一一复制给a
  for(int y=low;y<=high;y++) a[y++]=tmp[y++];
  //收尾
  delete[]tmp;
}

template<class OTHER,class KEY>
void mergeSort(SET<OTHER,KEY>a[],int low,int high)
{
    if(low>=high) return;
    int mid=(low+high)/2;
    mergeSort(a,low,mid);//归并前半部分
    mergeSort(a,mid+1,high);//归并后半部分
    merge(a,low,mid+1,high);//注意这里mid+1,是后半部分第一个元素
}

基数排序

时间复杂度O(N)

#include <iostream>
using namespace std;
//基数排序对于每个口袋中元素采用单链表方式连接
//定义一个集合
template<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
 OTHER other;//此处可以放结构体来储存其他信息
};

template<class OTHER>
struct Node
{
    Node*next;
    SET<int,OTHER>data;//用int表示key值
    Node(SET<int,OTHER>data1):data(data1){next=NULL;}
    Node(){next=NULL;}
};

template <class OTHER>
void bucketSort(Node<OTHER>*&p)//直接传入链表头
{
    Node<OTHER>*tail;
    //先找到里面最大项判断位数
    int max=0,len=0;
    for(tail=p;tail!=NULL;tail=tail->next)//注意链表用在for中
    {
        if(tail->data.key>max)max=tail->data.key;
    }
    if(max==0)len=0;
    else
    {
        while(max>0)
            {max/=10;
             len++;
            }
    }//确定位数

    Node<OTHER>*bucket[10],*last[10];
    int base=1;
    //bucket[i]指向每个框,last[i]指向每个框中挂着的最后一个单链表
    for(int i=0;i<len;i++)
    {
     for(int j=0;j<9;j++) bucket[j]=last[j]=NULL;//初始化框的指针、
     while(p!=NULL)
     {
         int k=p->data/base%10;//取出每个p中数据base位数
         if(bucket[k]==NULL) bucket[k]=last[k]=p;
         else last[k]->next=p;
         p=p->next;
     }//把数按照最后一位分配到各个箩筐中
     //接下来将各个箩筐连接起来(各箩筐内部最后一个单链表指向下一个箩筐开头)
     for(int j=0;j<9;j++)
     {
         //考虑到一些箩筐中可能没有装
         if(bucket[j]=NULL) continue;
         //将第一个bucket与p连接起来
         if(p==NULL) p=bucket[j];
         else
        {tail->next=bucket[j];}
        tail=last[j];
     }
     tail->next=NULL;
     base*=10;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值