您的位置:首页 > 其它

排序算法

2015-08-08 09:05 218 查看
冒泡

交换相邻的点使得最小的点排到最前,同时后面的点一定程度上也排序。

#include<iostream>
#include<string>
using namespace std;

void Bubble(int *list,int length)
{
bool flag=true;
for(int i=0;i<=length-1&&flag;i++)
{
flag=false;
for(int j=length-1;j>=i+1;j--)
{
if(list[j]<list[j-1])
{
int temp=list[j];
list[j]=list[j-1];
list[j-1]=temp;
flag=true;
}
}
}
}


简单选择

查找最小的点,把它放到最前面。

void SelectSort(int * list ,int length)
{
for(int i=0;i<length-1;i++)
{
int min=i;
for(int j=i+1;j<length;j++)
{
if(list[j]<list[min])
{
min=j;
}
}
if(i!=min)
{
int temp=list[min];
list[min]=list[i];
list[i]=temp;
}
}

}


直接插入

将第i+1个点插入到已排好序的前i个点中。

void InsertSort(int* list ,int length)
{
for(int i=1;i<length;i++)//已经排好前i个数,处理第i+1个即下标i的
{
int j=i-1;//前i个中的最后一个的下标
int tempi=list[i];
for(;j>=0&&tempi<list[j];j--)
{
list[j+1]=list[j];
}
list[j+1]=tempi;
}

}


希尔

其实有点类似直接插入,是分成好几组进行的。增量序列为dlta[k]=2t-k+1-1(0<=k<=t<=log2(n+1))。

第一层do while循环是increment逐次减一,直到increment为1

第二层for循环是比较i和i+increment项,i从头到尾

第三层for循环是为了移动,将比第i+increment项大的都向后移

void ShellSort(int*list,int length)
{
int increment=length/3+1;
do
{
increment=increment/3+1;
for(int i=0;i<=length-increment-1;++i)
{
int temp=list[i+increment];
int j=i;
for(;j>=0&&temp<list[j];j-=increment)
{
list[j+increment]=list[j];
}
list[j+increment]=temp;
}
}while(increment>1);
}


堆排序

先构建最大堆,即先将子树变成最大堆,交换1号和最后一个,再将去掉最后一个的序列调整成最大堆

void heapcore(int *list,int s,int m)
{
int temp=list[s];
int j=2*s;
for(;j<=m;j*=2)
{
if(j<m&&list[j]<list[j+1])
j++;
if(temp>=list[j])
break;
list[j/2]=list[j];
list[j]=temp;
}
}
void HeapSort(int*list ,int length)
{
for(int i=(length-1)/2;i>=1;--i)
{
heapcore(list,i,length-1);
}
for(int i=length-1;i>=2;--i)
{
int temp=list[1];
list[1]=list[i];
list[i]=temp;
heapcore(list,1,i-1);
}
}


快速

先随机选择一个数,将小于它的放在左边,大于的放在右边。返回该数的位置,然后处理左边序列,右边序列其中放置其他数的方法是,设置一个small标志,从start开始,遇到比轴小的就交换i和small位置的数,small加1

int partition(int *list ,int start,int end)
{
int idex=rand()%(end-start+1)+start;
int small=start;
int key=list[idex];
list[idex]=list[end];
list[end]=key;
for(int i=start;i<end;i++)
{
if(list[i]<key)
{
int temp=list[small];
list[small]=list[i];
list[i]=temp;
small++;
}

}
int temp=list[small];
list[small]=list[end];
list[end]=temp;
return small;
}
void QSort(int*list,int start,int end)
{
int id=partition(list ,start,end);
if(id>start)
QSort(list,start,id-1);
if(id<end)
QSort(list,id+1,end);
}
void QuickSort(int*list,int length)
{
QSort(list,0,length-1);
}


归并

先两个两个的,再四个四个的,后八个八个的排。。。

//排s1~s2-1(有序),s2~end(有序)两段,排好放在temp
void Merge(int *list,int *temp,int s1,int s2,int end )
{
int i=s1;
int j=s2;
int k=s1;
while(i<=s2-1&&j<=end)
{
if(list[i]<list[j])
{
temp[k]=list[i];
i++;
k++;
}
else
{
temp[k]=list[j];
j++;
k++;
}
}
if(i<=s2-1)
{
while(i<=s2-1)
{
temp[k]=list[i];
i++;
k++;
}
}
if(j<=end)
{
while(j<=end)
{
temp[k]=list[j];
j++;
k++;
}
}
}
//从第0个开始,相邻两个k个合并,即0~k-1,k~2k-1合并,2k~3k-1,3k~4k-1合并。。。
void MSort(int*list,int *temp,int k,int length)
{
int i=0;
//i是第一个k个的第一个i+2k-1是第二个k个的最后一个,要保证在长度范围内
for(;i+2*k-1<=length-1;i=i+2*k)
{
Merge(list,temp,i,i+k,i+2*k-1);
}
//剩下的不足2k个,可能>k&&<2k或者<=k
//i+k-1是第二个k个的第一个,说明存在第二个k个,需要合并
if(i+k-1<=length-1)
{
Merge(list,temp,i,i+k,length-1);
}
//不足k个,不用合并,直接复制
else
{
for(int j=i;j<=length-1;j++)
temp[j]=list[i];
}
}
void MergeSort(int*list,int length)
{
int *temp=new int[length];
int k=1;
while(k<length)
{
//这样做主要是为了将temp合并到list里面
MSort(list,temp,k,length);
k*=2;
MSort(temp,list,k,length);
k*=2;
}
delete[] temp;
}


int main()
{
int a[1000];
int i=0;
int c;
while(cin>>c)
{
a[i]=c;
i++;
if(cin.get()=='\n')
break;
}
//Bubble(a,i);
//SelectSort(a,i);
//InsertSort(a,i);
//ShellSort(a,i);
//HeapSort(a,i);
//QuickSort(a,i);
MergeSort(a,i);
for(int j=0;j<i;j++)
{
cout<<a[j]<<" ";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: