排序方法Word下载.docx
《排序方法Word下载.docx》由会员分享,可在线阅读,更多相关《排序方法Word下载.docx(15页珍藏版)》请在冰豆网上搜索。
=0&
&
a[j]>
temp;
)
a[j+1]=a[j];
--j;
}
a[j+1]=temp;
}
//递归的插入排序
voidRecursiveInsertSort(inta[],intn)
inti,j,key;
if(n>
1)
RecursiveInsertSort(a,n-1);
key=a[n-1];
i=n-2;
while(i>
a[i]>
key)
a[i+1]=a[i];
i--;
a[i+1]=key;
//折半插入排序
voidBinInsertSort(inta[],intn)
inti,j;
//在a[0..i-1]中折半查找插入位置使a[high]<
=a[i]<
a[high+1..i-1]
intlow=0,high=i-1,m=0;
while(low<
=high)
m=m+(high-low)/2;
if(a[i]<
a[m])high=m-1;
elselow=m+1;
//向后移动元素a[high+1..i-1],在a[high+1]处插入a[i]
intx=a[i];
for(j=i-1;
j>
high;
j--)
a[high+1]=x;
//完成插入
此算法的时间复杂度为O(n2)
2.快速排序
快速排序是一种基于交换的排序方法,最常见的有冒泡排序(BubbleSort),快速排序(改进的冒泡排序)(QuickSort)
下面先说冒泡排序:
冒泡排序的基本思想是在一次排序中,将最大的元素沉入底部,然后缩小范围,继续进行。
具体的说:
取第一个元素,然后与第二个元素进行比较,如果比第二个大,那么交换,否则,不交换,然后取第二个元素与第三个元素比较,同样用前面的方法,大则交换,直到将最大的元素交换到最底部,这是第一遍排序结束,然后,缩小范围,从第二个元素开始,在此运用上面的一遍排序方法。
直到范围缩小为一个元素的时候,排序结束。
快速排序是不稳定的。
最理想情况算法时间复杂度O(nlog2n),最坏O(n^2)。
//快速排序
voidQuickSort(inta[],intlow,inthigh)
if(low<
high)
//划分
intpivot=a[low];
inti=low;
intj=high;
while(i<
j)
while(i<
j&
=pivot)j--;
a[i]=a[j];
a[i]<
=pivot)i++;
a[j]=a[i];
a[i]=pivot;
//对子序列快排
QuickSort(a,low,i-1);
QuickSort(a,i+1,high);
//快速排序法的划分操作
intPartition(intvec[],intlow,inthigh)
//任选元素作为轴,这里选首元素
intpivot=vec[low];
high&
vec[high]>
=pivot)
high--;
vec[low]=vec[high];
vec[low]<
low++;
vec[high]=vec[low];
//此时low==high
vec[low]=pivot;
returnlow;
//in-placepartitionalgorithm
intin_place_partition(int*array,intleft,intright)
intpivot_index=(right-left)/2;
intpivot=array[pivot_index];
swap(array[pivot_index],array[right]);
intindex=left;
for(inti=left;
right;
if(array[i]<
pivot)//升序
swap(array[index],array[i]);
++index;
swap(array[right],array[index]);
returnindex;
voidQsort(int*array,intleft,intright)
if(left>
=right)
return;
intindex=Partition(array,left,right);
Qsort(array,left,index-1);
Qsort(array,index+1,right);
3.选择排序
选择排序(SelectionSort)的基本思想是,每一趟排序在n-i+1(i=1,2,3....,n-1)中选取关键字最小的记录作为有序序列的第i个记录。
(1)最为简单的是简单选择排序(SampleSelectionsort)
//选择排序
voidSelectSort(inta[],intn)
for(i=0;
intk=i;
for(j=i+1;
j<
j++)
if(a[j]<
a[k])k=j;
if(k!
=i)
a[i]=a[k];
a[k]=temp;
4.归并排序
归并排序(Mergingsort),所谓归并,简单的讲,就是将两个有序的序列,合成一个新的有序表。
我们用这个思想,可以把一个n个元素的序列,看成n个长度为1的子序列,然后利用归并排序,两两合并,然后的到了n/2个长度为2的子序列,再次进行合并,重复上面的步骤,直到合并为一个序列,则归并完成。
归并排序的时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlog2n)。
归并排序是稳定的排序算法
//将有序序列a[low..mid]和a[mid+1..high]归并到a[low..high]。
voidMerge(inta[],intlow,intmid,inthigh)
//归并到b[]
intj=mid+1;
intk=0;
int*b=newint[high-low+1];
=mid&
=a[j]){b[k++]=a[i++];
else{b[k++]=a[j++];
//归并剩余元素
=mid)b[k++]=a[i++];
while(j<
=high)b[k++]=a[j++];
//从b[]复制回a[]
=high-low;
++i)
a[low+i]=b[i];
delete[]b;
//归并排序
//http:
//en.wikipedia.org/wiki/Mergesort
voidMergeSort(inta[],intlow,inthigh)
if(low>
=high)return;
else
intmid=(low+high)/2;
MergeSort(a,low,mid);
MergeSort(a,mid+1,high);
Merge(a,low,mid,high);
//自底向上的归并排序
voidMergeSort2(inta[],intn)
ints,i,t=1;
while(t<
n)
s=t;
t=s*2;
for(i=0;
i+t<
=n;
i+=t)
Merge(a,i,i+s-1,i+t-1);
if(i+s<
Merge(a,i,i+s-1,n-1);
归并排序在最坏的情况下都是O(NlogN)的时间复杂度,缺点是Merge的时候要有O(N)的额外的空间,如何改进?
//reversearray
voidreverse(intarr[],intsize)
intleft=0;
intright=size-1;
while(left<
right)
inttemp=arr[left];
arr[left++]=arr[right];
arr[right--]=temp;
//swap[arr,arr+headSize)and[arr+headSize,arr+headSize+endSize)
voidSwapMemory(intarr[],intheadSize,intendSize)
reverse(arr,headSize);
reverse(arr+headSize,endSize);
reverse(arr,headSize+endSize);
//原地归并
voidInplace_Merge(intarr[],intbeg,intmid,intend)
inti=beg;
//指示有序串1
intj=mid+1;
//指示有序串2
j&
=end)
arr[i]<
=arr[j])
++i;
intindex=j;
=end&
arr[j]<
=arr[i])
++j;
SwapMemory(&
arr[i],index-i,j-index);
//swap[i,index)and[index,j)
i+=(j-index);
//原地归并排序
voidInplace_MergeSort(intarr[],intbeg,intend)
if(beg<
end)
intmid=(beg+end)/2;
Inplace_MergeSort(arr,beg,mid);
Inplace_MergeSort(arr,mid+1,end);
Inplace_Merge(arr,beg,mid,end);
5.冒泡排序(BubbleSort)
冒泡排序方法是最简单的排序方法。
这种方法的基本思想是,将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮。
在冒泡排序算法中我们要对这个“气泡”序列处理若干遍。
所谓一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻的元素的顺序是否正确。
如果发现两个相邻元素的顺序不对,即“轻”的元素在下面,就交换它们的位置。
显然,处理一遍之后,“最轻”的元素就浮到了最高位置;
处理二遍之后,“次轻”的元素就浮到了次高位置。
在作第二遍处理时,由于最高位置上的元素已是“最轻”元素,所以不必检查。
一般地,第i遍处理时,不必检查第i高位置以上的元素,因为经过前面i-1遍的处理,它们已正确地排好序。
冒泡排序是稳定的。
算法时间复杂度是O(n^2)。
//冒泡排序(相邻比较法)
voidBubbleSort(inta[],intn)
n-1;
for(j=0;
n-i-1;
if(a[j]>
a[j+1])
temp=a[j];
a[j]=a[j+1];
//改进的冒泡排序
voidImprovedBubbleSort(inta[],intn)
boolchange=false;
change=false;
for(intj=0;
change=true;
if(!
change)break;
//双向冒泡排序(鸡尾酒排序)
voidCocktailSort(inta[],intn)
inttop=n-1;
intbottom=0;
boolflag=true;
while(flag)
flag=false;
//从小到大,升序
for(i=bottom;
top;
if(a[i]>
a[i+1])
swap(a[i],a[i+1]);
flag=true;
bottom++;
//从大到小,降序
for(j=top;
bottom;
a[j-1])
swap(a[j],a[j-1]);
top--;
6.希尔排序(ShellSort)
先将待排序列分割成若干个子序列,分别进行直接插入排序,基本有序后再对整个序列进行直接插入排序。
希尔排序是不稳定的。
时间复杂度大约为O(n^3/2)。
//希尔排序:
shell排序的核心仍然使用插入排序
voidShellSort(inta[],intn)
intdk=n/2;
while(dk>
=1)
//一趟希尔排序,对dk个序列分别进行插入排序
for(i=dk;
for(j=i-dk;
x;
j-=dk)
a[j+dk]=a[j];
a[j+dk]=x;
dk=dk/2;
//缩小增量
7.堆排序(HeapSort)
堆排序是一种树形选择排序,在排序过程中,将A[n]看成是完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
对N个元素从小到大排序建立大根堆,然后交换堆顶与最后一个元素,将剩下的N-1个元素调整为大根堆,执行N-1此这样的操作。
堆排序是不稳定的。
算法时间复杂度O(nlogn)。
//调整大根堆
voidHeapAdjust(intdata[],intnStart,intnLen)
intnMaxChild=0;
intTemp;
while((2*nStart+1)<
nLen)
nMaxChild=2*nStart+1;
if((2*nStart+2)<
//比较左子树和右子树,记录最大值的Index
if(data[2*nStart+1]<
data[2*nStart+2])
nMaxChild=2*nStart+2;
//changedata
if(data[nStart]<
data[nMaxChild])
//交换nStart与nMaxChild的数据
Temp=data[nStart];
data[nStart]=data[nMaxChild];
data[nMaxChild]=Temp;
//堆被破坏,需要重新调整
nStart=nMaxChild;
//比较左右孩子均小则堆未破坏,不再需要调整
break;
//堆排序从小到大排序建立大顶堆
voidHeapSort(intdata[],intnLen)
inti;
intnTemp;
//建立堆
for(i=nLen/2-1;
i>
=0;
i--)
HeapAdjust(data,i,nLen);
for(i=nLen-1;
0;
//交换堆顶元素和最后一个元素
nTemp=data[0];
data[0]=data[i];
data[i]=nTemp;
//将data[0...i]重写建成大根堆
HeapAdjust(data,0,i);
三、详细设计
四、调试分析
五、用户手册
六、测试结果
七、附录