排序改进算法
1. 选择法排序和改进选择法排序
//选择排序法void SelectSort(int data[],int n){ int i,j,temp,min,pos,flag; for(i=0;i<n-1;i++)//扫描n-1次,由i=0,1,...,n-2 { //顺序查找data[i]至data[n-1]之间的最小值及位置 min=data[i]; pos=i; flag=0;//假设data[i]为最小值 for(j=i+1;j<n;j++) { if(min>data[j]) { min=data[j]; pos=j; flag=1; } } if(flag==1)//如果最小值改变,则进行交换 { temp=data[i]; data[i]=data[pos]; data[pos]=temp; }
} cout<<"选择排序后的数据为: "; Display(data,N);}
改进排序就是将待排序的第一个数据与为排序的最小的一个交换,这样每趟就只需要交换一次;而没有改进的话,可能要进行多次交换。
2. 对内排序算法的改进及性能比较
public class XPX
{
public static void main(String args[])
{
int i,j,t,min;
int a[]={9,8,7,6,5,4,3,2,1};
for(i=0;i<8;i++)
{
min = a[i];
for(j=i;j<a.length;j++)
{
if(min>a[j])
{
min = a[j];
a[j]=a[i];
a[i]=min;
}
}
}
for(i=0;i<a.length;i++)
{
System.out.print(" "+a[i]);
}
System.out.println();
}
}
3. 排序有几种方法
一. 冒泡排序
冒泡排序是是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来。遍历数列的工作是重复的进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端
1.冒泡排序算法的运作如下:
(1)比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个
(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素还是最大的数
(3)针对所有的元素重复以上的步骤,除了最后一个
二. 选择排序
选择排序是一种简单直观的排序算法。他的工作原理如下:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,他们当中至少有一个将被移到最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换去移动 元素的排序方法中,选择排序属于非常好的一种
三. 插入排序
插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在从后向前扫描的过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间
四. 快速排序
快速排序,又称划分交换排序。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都要小,然后再按此方法对两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
五 希尔排序过程
希尔排序是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
六. 归并排序
归并排序是采用分治法(把复杂问题分解为相对简单的子问题,分别求解,最后通过组合起子问题的解的方式得到原问题的解)的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组
将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,水小九先取谁,取了后相应的指针就往后移一位。然后比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可
4. c语言冒泡排序有什么改进办法吗
1.设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
改进后算法如下:
voidBubble_1(intr[],intn){
inti=n-1;//初始时,最后位置保持不变
while(i>0){
intpos=0;//每趟开始时,无记录交换
for(intj=0;j<i;j++)
if(r[j]>r[j+1]){
pos=j;//记录交换的位置
inttmp=r[j];r[j]=r[j+1];r[j+1]=tmp;
}
i=pos;//为下一趟排序作准备
}
}
2.传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) ,从而使排序趟数几乎减少了一半。
改进后的算法实现为:
voidBubble_2(intr[],intn){
intlow=0;
inthigh=n-1;//设置变量的初始值
inttmp,j;
while(low<high){
for(j=low;j<high;++j)//正向冒泡,找到最大者
if(r[j]>r[j+1]){
tmp=r[j];r[j]=r[j+1];r[j+1]=tmp;
}
--high;//修改high值,前移一位
for(j=high;j>low;--j)//反向冒泡,找到最小者
if(r[j]<r[j-1]){
tmp=r[j];r[j]=r[j-1];r[j-1]=tmp;
}
++low;//修改low值,后移一位
}
}
5. 快速排序算法
快速排序(Quicksort)是对冒泡排序的一种改进。
然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
6. 排序算法使用(改进的)冒泡排序算法。
#i nclude <stdlib.h>
#i nclude <time.h>
void maopao(int source[],int n)
{
int start=0,end=n-1;
int i;
while(start<=end)/*如果还有元素没有确定其位置*/
{
for(i=start;i<end;i++)/*寻找剩余元素的最大数*/
if(source[i]>source[i+1])
{
int t;
t=source[i];
source[i]=source[i+1];
source[i+1]=t;
}
end--;/*找到最大数*/
for(i=end;i>start;i--)/*寻找剩余元素的最小元素*/
if(source[i]<source[i-1])
{
int t;
t=source[i];
source[i]=source[i-1];
source[i-1]=t;
}
start++;/*找到一个最小数*/
}
}
void output(int data[],int n)
{
int i;
for(i=0;i<n;i++)
{
if(i%10==0)
printf("\n");
printf("%4d",data[i]);
}
}
int check(int data[],int n)
{/*检查结果数据是否已升序排列*/
int i;
for(i=0;i<n-1;i++)
if(data[i]>data[i+1])
return 0;
return 1;
}
void main()
{
int data[500];
int i;
srand(time(NULL));
for(i=0;i<500;i++)
data[i]=random(500);
printf("\nThe original data is:\n");
output(data,500);
maopao(data,500);
printf("\nAfter sort:\n");
output(data,500);
printf("\n");
if(check(data,500)==1)
printf("\nRight.");
else
printf("\nWrong.");
}
7. 数据结构中快速排序算法的不足以及改进
一般快速排序算法都是以最左元素作为划分的基准值,这样当数据元素本身已经完全有序(不管正序或者逆序)时,每一趟划分只能将一个元素分割出来,其效率很低:时间复杂度O(n^2),空间复杂度为O(n)
所以改进方法就是找寻合适的基准值,保证不至于在关键字有序或者接近有序时发生这个情况,一般可以使用三者取中(就是待划分序列的头元素、尾元素、中间元素三者的中间值)、或者随机选择等方法,这样即使关键字完全有序,也可以保证时间复杂度O(nlogn),空间复杂度O(logn)
8. 谁能给我几种排序的具体算法(直接插入,折半插入,冒泡,简单选择,快速,堆,归并排序)
直接插入排序
说明:逐个将后一个数加到前面的排好的序中。在直接插入排序过程中,对其中一个记录的插入排序称为一次
排序;直接插入排序是从第二个记录开始进行的,因此,长度为n的记录序列需要进行n-1次排序才能完成整个
序列的排序。时间复杂度为O(n2)。
void InsertSort(elemtype x[],int n)
/*用直接插入法对x[0]-x[n-1]排序*/
{
int i,j;
elemtype s;
for(i=0;i<n-1;i++)
{
s=x[i+1];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+1]=x[j];
j--;
}
x[j+1]=s;
}
}
---------------------
希尔排序
说明:希尔排序又称缩小增量排序,增量di可以有各种不同的取法,但最后一次排序时的增量必须为1,最简
单可取di+1=di/2(取小)。时间复杂度为O(n(log2n)2)。
void ShellSort(elemtype x[],int n,intd[],int Number)
/*用希尔排序法对记录x[0]-x[n-1]排序,d为增量值数组*/
/*Number为增量值个数,各组内采用直接插入法排序*/
{
int i,j,k,m,Span;
elemtype s;
for(m=0;m<Number;m++)
{
Span=d[m];
for(k=0;k<Span;k++)
{
for(i=k;i<n-1;i+=Span)/*这个for之后的是“组内采用直接插入法排序”*/
{
s=x[i+Span];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+Span]=x[j];
j-=Span;
}
x[j+Span]=s;
}
}
}
}
----------------------------
直接选择排序
说明:每次将后面的最小的找出来插入前面的已排好的序中。同理,具有n个记录的序列要做n-1次排序。
时间复杂度为O(n2)。
void SelectSort(elemtype x[],int n)
/*用直接选择排序法对x[0]-x[n-1]排序*/
{
int i,j,Small;
elemtype Temp;
for(i=0;i<n-1;i++)
{
Small=i;
for(j=i+1;j<n;j++)
if(x[j].key<x[Small].key)
Small=j;
if(Small!=i)
{
Temp=x[i];
x[i]=x[Small];
x[Small]=Temp;
}
}
}
--------------------------
冒泡排序
说明:两个两个比较,将大的往后移。通过第一次冒泡排序,使得待排序的n个记录中关键字最大的记录排到
了序列的最后一个位置上。然后对序列中前n-1个记录进行第二次冒泡排序。。。对于n个记录的序列,共需进
行n次冒泡排序。时间复杂度为O(n2)。
void BubbleSort(elemtype x[],int n)
/*用冒泡排序法对x[0]-x[n-1]排序*/
{
int i,j,flag=1;
elemtype Temp;
for(i=1;i<n&&flag==1;i++)
{
flag=0;
for(j=0;j<n-i;j++)
{
if(x[j].key>x[j+1].key)
{
flag=1;
Temp=x[j];
x[j]=x[j+1];
x[j+1]=Temp;
}
}
}
}
-----------------------------
快速排序
说明:又叫分区交换排序,是对冒泡排序方法的一种改进。时间复杂度为O(nlog2n)。
void QuickSort(elemtype x[],int low,int high)
/*用递归方法对记录x[0]-x[n-1]进行快速排序*/
{
int i,j;
elemtype Temp;
i=low;
j=high;
Temp=x[low];
while(i<j)
{
/*在序列的右端扫描*/
while(i<j&&Temp.key<=x[j].key)j--;
if(i<j)
{
x[i]=x[j];
i++;
}
/*在序列的左端扫描*/
while(i<j&&x[i].key<Temp.key)i++;
if(i<j)
{
x[j]=x[i];
j--;
}
}
x[i]=Temp;
/*对子序列进行快速排序*/
if(low<i-1)QuickSort(x,low,i-1);
if(j+1<high)QuickSort(x,j+1,high);
}
-------------------------
归并排序
说明:所谓归并排序就是将两个或两个以上的有序数据序列合并成一个有序数据序列的过程。
时间复杂度为O(nlog2n)。
void merge(r,l,m,h,r1,r2)/*r[l,m]及r[m+1,h]分别有序,归并后置于r2中*/
sqlist r,r2;
int l,m,h;
{
int i,j,k;
k=l;/*k是r2的指示器,i、j分别为s1、s2的指示器*/
i=l;
j=m+1;
while(i<=m&&j<=h)
{
if(r[i].key<=r[j].key)
{
r2[k]=r[i];
i++;
}
else
{
r2[k]=r[j];
j++;
}
k++;
}
if(i>m) /*s1结束*/
while(j<=h)
{
r2[k]=r[j];
j++;k++;
}
else
while(i<=m)
{
r2[k]=r[i];
i++;k++;
}
}
9. 求一个插入排序和冒泡排序的改进算法
This is C++ code.
插入排序:
bool insertionsort(int *array,int n)
{
int temp; //用来存储,插入的数据
for(int i=1;i<n;i++)
{
temp=array[i]; //用temp记录array[i]
for(int j=i-1;j>=0;j--) //逐个向前寻找插入点
{
if(temp>array[j]) //找到,跳出循环
break;
else //没找到,将前一个数据后移
array[j+1]=array[j];
}
array[j+1]=temp;
}
return true;
}
复制代码思想: 逐个取数,插入一个有序数组(从后向前插)
算法平均时间复杂度: O(n^2)
冒泡排序:
bool bottomupsort(int *array,int n)
{
int length=1,temp_length,i; //temp_length表示单个合并数组的长度
while(length<n)
{
temp_length=length; //length表示合并后数组的长度
length=2*temp_length;
i=0; //i用于记录合并数组的起始位置
while(i+length-1<=n-1)
{
merge(array,i,i+temp_length,i+length-1); //合并i~i+temp_length-1 和 i+temp_length~i+length-1 段
i=i+length; //取下一个合并段的起始位置
}
if(i+temp_length<n-1)
merge(array,i,i+temp_length,n-1); //对尾部剩余段合并
}
return true;
}
bool merge(int *array,int start1,int start2,int n) //合并两个有序数组
{
int temp_n=n-start1+1, //两合并数组的长度和
*temp_array,
n1=start2-1, //第一个有序数组的末端位置
temp_start1=start1; //记录start1的初始位置
temp_array=(int *)malloc(sizeof(int)*temp_n); //申请长度为temp_n的整形空间,用于临时存储合并后的数组
for(int i=0;start1<=n1&&start2<=n;i++) //对两个有序数组进行合并,存储于temp_array
{
if(array[start1]<=array[start2])
{
temp_array[i]=array[start1];
start1++;
}
else
{
temp_array[i]=array[start2];
start2++;
}
}
if(start1<=n1)
{
while(start1<=n1)
{
temp_array[i++]=array[start1];
start1++;
}
}
else
{
while(start2<=n)
{
temp_array[i++]=array[start2];
start2++;
}
}
for(i=0,start1=temp_start1;i<temp_n;start1++,i++) //将合并后的有序数组,复制到array数组中
{
array[start1]=temp_array[i];
}
free(temp_array);
return true;
}
算法平均时间复杂度: O(nlogn)
10. 快速排序算法原理与实现
快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2、以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5、重复第3、4步,直到I=J。
(10)排序改进算法扩展阅读:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1、设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2、以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3、从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]的值赋给A[i];
4、从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]的值赋给A[j];
5、重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。