八大排序算法C/C++代码实现
八大排序算法代码实现
tip:
本文所有排序算法均为升序排序
基本数据结构
typedef int dataType;
//这里主要针对整型数据进行排序
typedef struct
{
vector<dataType> key; //顺序表关键字
int length; //顺序表长度
}List;
tip:
这里vector<dataType>
表示以储存dataType
类型的vector
定义的对象key
在本文中的用途与数组基本无差别,可用dataType key[SIZE];
代替
使用vector
不要忘了
#inlude<vector>
一、插入排序
原始版本
//排序部分为0-L.length-1
void InsertSort_0(List &L)//对顺序表L进行插入排序
{
int i,j;
dataType temp;
for(i=1;i<L.length;i++)
{
//将i号数据插入0到i-1的有序序列中
temp = L.key[i];
for(j=i-1;j>=0;j--)//向前寻找应该插入该数据的位置
{
if(L.key[j]>temp)
L.key[j+1] = L.key[j];
else
break;
}
L.key[j+1] = temp;
}
}
改进版本1
将顺序表的0号位置清空,作为哨兵位,在1到length的位置放置数据,可以省去循环出口判断的时间,也无需额外的变量来临时储存插入的数据
//排序部分为1-L.length
void InsertSort_1(List &L)
{
int i,j;
for(i=2;i<=L.length;i++)//注意这里开始和结束的位置和之前有所不同
{
L.key[0] = L.key[i];//将要插入的数据放到哨兵位上
for(j=i-1;;j--)
{
if(L.key[j]>L.key[0])
L.key[j+1]=L.key[j];
else
break;
}
L.key[j+1] = L.key[0];
}
}
改进版本2
在寻找插入数据应该插入的位置时本质上是在做一个顺序查找,我们可以用二分查找取而代之,能够更大程度地减小复杂度
//排序部分为1-L.length
void InsertSort_2(List &L)
{
int i,j,k;
int low,high,mid;
for(i=2;i<=L.length;i++)
{
L.key[0] = L.key[i];
low = 1; //查找区间下界
high = i-1; //查找区间上界
while(low<=high)
{
mid = (low+high)/2;
if(L.key[mid]>L.key[0])
high = mid-1; //在前一段区间查找
else
low = mid+1; //在后一段区间查找
}
//low即为应插入位置
//将有序部分插入位置后面的所有点后移一位
for(j=i-1;j>=low;j--)
L.key[j+1] = L.key[j];
L.key[low] = L.key[0];
}
}
二、希尔排序
//排序部分为1-L.length
void ShellInsert(List &L,int d)//增量为d的插入排序(以插入排序的改进版本1为基础)
{
int i,j;
for(i=d+1;i<=L.length;i++)
{
L.key[0] = L.key[i];
for(j=i-d;j>=0;j-=d)
{
if(L.key[j]>L.key[0])
L.key[j+d] = L.key[j];
else
break;
}
L.key[j+d] = L.key[0];
}
}
void ShellSort(List &L)
{
int i;
for(i=L.length/2;i>=1;i/=2)
ShellInsert(L,i);
}
三、冒泡排序
原始版本
//排序部分为0-L.length-1
void BubbleSort(List &L)
{
int i,j;
dataType temp;
for(i=1;i<=L.length-1;i++)//执行n-1次冒泡
{
for(j=0;j<L.length-i;j++)
if(L.key[j]>L.key[j+1])
{
temp = L.key[j];
L.key[j] = L.key[j+1];
L.key[j+1] = temp;
}
}
}
改进版本
当序列相对有序时无需进行过多的比较操作,每次冒泡记录下最后一次交换的位置,从0位置到标记位置即是无序部分,下一次冒泡只需比较到这里即可,当标记位置为0时,冒泡结束
//排序部分为0-L.length-1
void BubbleSort_1(List &L)
{
int i,sig,lastchange;
dataType temp;
sig = L.length-1;
while(sig>0)
{
lastchange = 0;
for(i=0;i<sig;i++)
{
if(L.key[i]>L.key[i+1])
{
temp = L.key[i];
L.key[i] = L.key[i+1];
L.key[i+1] = temp;
lastchange = i;
}
}
sig = lastchange;
}
}
四、快速排序
//排序部分为0-L.length-1
int pivot(List &L,int low,int high)//一趟快速排序,返回枢轴的位置
{
dataType temp = L.key[low];
while(low<high)
{
while(low<high && L.key[high]>=temp)//从右边找到比枢轴小的数据
high--;
L.key[low] = L.key[high];
while(low<high && L.key[low]<=temp)//从左边找到比枢轴大的数据
low++;
L.key[high] = L.key[low];
}
L.key[low] = temp;
return low;
}
void QSort(List &L,int low,int high)
{
if(low<high)
{
int pivotLoc = pivot(L,low,high);
QSort(L,low,pivotLoc-1); //对前一部分进行快速排序
QSort(L,pivotLoc+1,high); //对后一部分进行快速排序
}
}
void QuickSort(List &L)
{
QSort(L,0,L.length-1);
}
五、选择排序
经典算法
//排序部分为0-L.length-1
void SelectSort(List &L)
{
int i,j,k;
dataType temp;
for(i=0;i<L.length-1;i++)
{
temp = L.key[i];
k = i;
for(j=i+1;j<L.length;j++)
{
if(temp>L.key[j])
{
temp = L.key[j];
k = j;
}
}
L.key[k] = L.key[i];
L.key[i] = temp;
}
}
六、堆排序
建堆的过程中需要从L.length/2开始到0依次进行调整即可
//堆的结构采用顺序表形式储存
//为了做到升序排序,我们要构建一个大顶堆
//排序部分为1-L.length
void HeapAdjust(List &L,int low,int high)
{
int i=low,j=2*i;
L.key[0] = L.key[low];
while(j<=high)
{
if(j+1<=high && L.key[j+1]>L.key[j]) //选取大的子树
j++;
if(L.key[j] > L.key[0]) //如果子树数据比其本身大,进行调整
{
L.key[i] = L.key[j];
i = j;
j = 2*i;
}
else
break;
}
L.key[i] = L.key[0];
}
void HeapSort(List &L)
{
int i;
for(i=L.length/2;i>0;i--) //建成大顶堆
HeapAdjust(L,i,L.length);
for(i=L.length;i>1;i--) //逐个移动,移动后调整
{
L.key[0] = L.key[1];
L.key[1] = L.key[i];
L.key[i] = L.key[0];
HeapAdjust(L,1,i-1);
}
}
七、归并排序
二路归并排序(递归)
先不断地对数组进行递归平分,一直分到不能再分,然后回溯的过程中两两进行数组归并操作
//排序部分为1-L.length
void Merge(List &S,List &L,int low,int mid,int high)
{
//将有序的S(low到mid)和有序的S(mid+1到high)归并成有序的T(low到high)
//这个函数的操作相当于两个数组的异地归并
int i = low,j = mid+1,k = low;
while(i<=mid && j<=high)
{
if(S.key[i]<=S.key[j])
{
L.key[k] = S.key[i];
i++;
k++;
}
else
{
L.key[k] = S.key[j];
j++;
k++;
}
}
while(i<=mid)
{
L.key[k] = S.key[i];
i++;
k++;
}
while(j<=high)
{
L.key[k] = S.key[j];
j++;
k++;
}
}
//将S的low到high部分归并为有序的到T中对应位置
void MSort(List &S,List &L,int low,int high)
{
int i;
int mid;
if(low<high)
{
mid = (low+high)/2; //对S平分
MSort(L,S,low,mid); //对前半段进行归并排序
MSort(L,S,mid+1,high);//对后半段进行归并排序
Merge(S,L,low,mid,high);//讲两部分归并
}
}
void MergeSort(List &L)
{
int i;
List S = L;
for(i=1;i<=L.length;i++)
S.key[i] = L.key[i];
MSort(S,L,1,L.length);
}
二路归并排序(非递归)
//排序部分为1-L.length
void Merge(List &S,List &L,int low,int mid,int high); //归并部分仍用之前的代码
void MergeSort_1(List &L)
{
int len,i,j;
List S = L;
for(len=1;len<=L.length;len*=2)
{
for(i=1;i<=L.length-2*len+1;i+=2*len)
Merge(S,L,i,i+len-1,i+2*len-1);
if(i+len<=L.length)
Merge(S,L,i,i+len-1,L.length);
S = L;
}
}
八、基数排序
tip:
在此算法中用到了vector的几个函数成员,在此进行说明
push_back(); //相当于出栈
size(); //返回vector的长度,相当于数组长度
clear(); //将vector中所有数据清空
对多位数的按数位进行的基数排序
typedef struct //队列结构
{
vector<dataType> data;
int start = 0;
}Queue;
//排序部分为0-L.length-1
void RadixSort(List &L)
{
//对0-9999的数据进行基数排序
const int maxIndex = 4;
int i,k;
int radix = 1;
int n;
Queue Q[10];
for(k=1;k<=maxIndex;k++)//分别对个十百千位进行处理
{
for(i=0;i<L.length;i++) //分配数据
{
n = (L.key[i]/radix)%10;
Q[n].data.push_back(L.key[i]);
}
for(i=0,n=0;n<10;n++) //收集数据
{
while(Q[n].start!=Q[n].data.size())
{
L.key[i] = Q[n].data[Q[n].start];
Q[n].start++;
i++;
}
Q[n].data.clear(); //重置队列
Q[n].start = 0;
}
radix*=10; //处理更高一位
}
}
对一般较小数字进行的二进制基数排序
//排序部分为0-L.length-1
void RadixSort_1(List &L)
{
int i,k;
int maxIndex;
int radix = 1;
int n;
Queue Q[2];
dataType max = L.key[0];
for(i=0;i<L.length;i++) //计算二进制最高位数
if(L.key[i]>max)
max = L.key[i];
maxIndex = sqrt(max)+1;
for(k=1;k<=maxIndex;k++) //分别对二进制的每一位进行处理
{
for(i=0;i<L.length;i++) //分配数据
{
n = (L.key[i]/radix)%2;
Q[n].data.push_back(L.key[i]);
}
for(i=0,n=0;n<2;n++) //收集数据
{
while(Q[n].start!=Q[n].data.size())
{
L.key[i] = Q[n].data[Q[n].start];
Q[n].start++;
i++;
}
Q[n].data.clear(); //重置队列
Q[n].start = 0;
}
radix*=2; //处理更高一位
}
}
本文持续更新中,如有错误或不足之处,欢迎批评指正。
本文来自博客园,作者:Vergissmeinnicht_z,转载请注明原文链接:https://www.cnblogs.com/Vergissmeinnicht-rj/p/16336179.html,欢迎访问本人个人主页:https://vergiss.cn