各类排序的实现
对于排序这个模块,一直想总结一下,但是确实排序的有太多太多,就借数据结构课上所学来总结一下,感觉以后ACM可以用的上。
基本排序分类
其中最基础的有直接插入排序,简单选择排序与冒泡排序,不用多说了。
希尔排序:
先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
快速排序:
其实是起泡排序的一种改进,它解决了起泡排序中只有相邻元素之间才能交换的问题。它首先确定一个轴值(pivot(它是比较的基准)),将待排序记录划分成两部分,左侧记录均小于或等于轴值,右侧记录均大于或等于轴值,然后分别对这两部分重复上述过程,直到整个序列有序。
堆排序:
首先将待排序序列调整成一个堆,此时,选出了堆中所以记录的最大者即堆顶的记录,将堆顶记录移走,然后将剩余记录再调整成堆,重复上述操作,直到堆中只有一个记录。
归并排序:
将若干个有序序列逐步归并,最终归并为一个有序数列。(有待学习emmm~)
可添加swap()函数,使得代码更简洁
void swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp;
}
这是以下排序的时间性能:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
class Sort{
public :
Sort(int r[],int n);//构造函数,生成待排序数列
~Sort();//析构函数
//插入排序:
void InsertSort();//直接插入排序
void ShellSort();//希尔排序
//交换排序:
void BubbleSort();//冒泡排序
void QuickSort(int first,int last);//快速排序
//选择排序:
void SelectSort();//简单选择排序
void HeapSort();//堆排序
//归并排序:
void MergeSort1(int first,int last);//二路归并递归排序
void MergeSort2();//二路归并非递归排序
void Print();//输出
private:
int Partition(int first,int last);//快速排序,一次划分
void Sift(int k,int last);//堆排序,堆调整
void Merge(int first1,int last1,int last2);//归并排序,合并相邻有序数列
void MergePass(int h);//归并排序,一趟归并
int *data;//待排序数列
int length;
};
Sort::Sort(int r[],int n){
data=new int[n];
for(int q=0;q<n;q++)
{
data[q]=r[q];
}
length=n;
}
Sort::~Sort(){
delete[] data;
}
void Sort::Print(){
for(int q=0;q<length;q++)
{
cout<<data[q]<<" ";
}
cout<<endl;
}
//直接插入排序:
void Sort::InsertSort(){
int i,j,temp;
for(i=1;i<length;i++)
{
temp=data[i];
for(j=i-1;j>=0&&temp<data[j];j--)
{
data[j+1]=data[j];
}
data[j+1]=temp;
}
}
//希尔排序:
void Sort::ShellSort(){
int d,i,j,temp;
for(d=length/2;d>=1;d=d/2)//增量为d进行直接插入排序
{
for(i=d;i<length;i++)//进行一趟希尔排序
{temp=data[i];//暂存待插入记录
for(j=i-d;j>=0&&temp<data[j];j-=d)
{data[j+d]=data[j];}//记录后移d个位置
data[j+d]=temp;
}}}
//起(冒)泡排序:
void Sort::BubbleSort(){
int j,exchange,bound,temp;
exchange=length-1;//第一趟起泡的排序区间是[0~length-1]
while(exchange!=0)
{
bound=exchange;exchange=0;
for(j=0;j<bound;j++)//一趟起泡的排序区间是[0~bound]
{
if(data[j]>data[j+1]){
temp=data[j];data[j]=data[j+1];data[j+1]=temp;
exchange=j;//记录每一次交换的位置
}}}}
//
int Sort::Partition(int first,int last){
int i=first,j=last,temp;//初始化一次划分的区间
while(i<j){
while(i<j&&data[i]<=data[j])j--;//右侧扫描
if(i<j){
temp=data[i];data[i]=data[j];
data[j]=temp;
i++;
}
while(i<j&&data[i]<=data[j])i++;//左侧扫描
if(i<j){
temp=data[i];data[i]=data[j];
data[j]=temp;
j--;
}
}
return i;//i为轴值记录的最终位置
}
void Sort::QuickSort(int first,int last){
if(first>=last)return;//区间长度为1,递归结束
else{
int pivot=Partition(first,last);//一次结束
QuickSort(first,pivot-1);//对左侧子序列进行快速排序
QuickSort(pivot+1,last);//对右侧子序列进行快速排序
}
}
//简单选择排序:
void Sort::SelectSort(){
int i,j,index,temp;
for(i=0;i<length-1;i++)//进行length-1趟简单选择排序
{
index=i;
for(j=i+1;j<length;j++)//在无序区中选取最小记录
{if(data[j]<data[index])index=j;}
if(index!=i){
temp=data[i];data[i]=data[index];
data[index]=temp;
}
}
}
//堆排序:
void Sort::Sift(int k,int last){
int i,j,temp;
i=k;j=2*i+1;//i是被调整结点,j是i的左孩子
while(j<=last){//还没有进行到叶子
if(j<last&&data[j]<data[j+1])j++;//j指向左右孩子的较大者
if(data[i]>data[j]){break;}//已经是堆
else{
temp=data[i];
data[i]=data[j];
data[j]=temp;
i=j;
j=2*i+1;//被调整结点位于结点j的位置
}
}
}
void Sort::HeapSort(){
int i,temp;
for(i=ceil(length/2)-1;i>=0;i--)//从最后一个分支结点至根节点调整
{Sift(i,length-1);}
for(i=1;i<length;i++)
{temp=data[0];data[0]=data[length-i];data[length-i]=temp;
Sift(0,length-i-1);//重建堆
}
}
//二路归并排序:
void Sort::Merge(int first1, int last1, int last2)
{
int *temp = new int[length]; //数组temp作为合并的辅助空间
int i = first1, j = last1 + 1, k = first1;
while (i <= last1 && j <= last2)
{
if (data[i] <= data[j])temp[k++] = data[i++]; //取较小者放入temp[k]
else temp[k++] = data[j++];
}
while (i <= last1) //对第一个子序列进行收尾处理
temp[k++] = data[i++];
while (j <= last2) //对第二个子序列进行收尾处理
temp[k++] = data[j++];
for (i = first1; i <= last2; i++) //将合并结果传回数组r
{data[i] = temp[i];}
delete[ ] temp;
}
//二路归并递归排序:
void Sort::MergeSort1(int first, int last)
{
if (first == last) return; //待排序序列只有1个记录,递归结束
else {
int mid = (first + last)/2;
MergeSort1(first, mid); //归并排序前半个子序列
MergeSort1(mid+1, last); //归并排序后半个子序列
Merge(first, mid, last); //将两个已排序的子序列合并
}
}
//二路归并非递归排序:
void Sort::MergePass(int h)
{
int i = 0;
while (i + 2 * h <= length) //待归并记录有两个长度为h的子序列
{
Merge(i, i+h-1, i+2*h-1);
i = i + 2 * h;
}
if (i + h < length)
Merge(i, i+h-1, length-1); //两个子序列一个长度小于h
}
void Sort::MergeSort2()
{
int h = 1; //初始时子序列长度为1
while (h < length)
{
MergePass(h); //一趟归并排序
h = 2 * h;
}}
int main()
{
int a[100000];
int n;
cin>>n;
fill_n(a,n+5,0);
for(int q=0;q<n;q++)
{
cin>>a[q];
}
Sort l(a,n);
//l.ShellSort();
//l.InsertSort();
//l.BubbleSort();
//l.QuickSort(0,n-1);
//l.SelectSort();
//l.HeapSort();
//l.MergeSort1(0,n-1);
l.MergeSort2();
l.Print();
return 0;
}
继续加油吧!