最新整理c#排序方法.docx
- 文档编号:8795347
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:13
- 大小:19.46KB
最新整理c#排序方法.docx
《最新整理c#排序方法.docx》由会员分享,可在线阅读,更多相关《最新整理c#排序方法.docx(13页珍藏版)》请在冰豆网上搜索。
最新整理c#排序方法
2011.4.11
(1)冒泡排序
依次比较相邻的两个数,将小数放在前面,大数放在后面。
即在第一趟:
首先比较第1个和第2个数,将小数放前,大数放后。
然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。
至此第一趟结束,将最大的数放到了最后。
在第二趟:
仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
如此下去,重复以上过程,直至最终完成排序。
冒泡排序是一种稳定排序算法。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceConsoleApplication3
{
classProgram
{
staticvoidMain(string[]args)
{
int[]a={3,4,7,10,5,9};
int[]b=BubbleSort(a);
for(inti=0;i { Console.Write(b[i].ToString()+""); } Console.ReadLine(); } publicstaticint[]BubbleSort(int[]list) { inti,temp; for(intj=0;j { for(i=list.Length-1;i>j;i--) { if(list[j] { temp=list[j]; list[j]=list[i]; list[i]=temp; } } } returnlist; } } } (2)选择排序 定位比较交换法: 设有10个数分别存在数组元素a[0]~a[9]中。 定位比较交换法是由大到小依次定位a[0]~a[9]中恰当的值(和武林大会中的比武差不多),a[9]中放的自然是最小的数。 如定位a[0],先假定a[0]中当前值是最大数,a[0]与后面的元素一一比较,如果a[4]更大,则将a[0]、a[4]交换,a[0]已更新再与后面的a[5]~a[9]比较,如果a[8]还要大,则将a[0]、a[8]交换,a[0]又是新数,再与a[9]比较。 一轮比完以后,a[0]就是最大的数了,本次比武的武状元诞生了,接下来从a[1]开始,因为状元要休息了,再来一轮a[1]就是次大的数,也就是榜眼,然后从a[2]开始,比出探花,真成比武大会了,当比到a[8]以后,排序就完成了。 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。 那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。 比较拗口,举个例子,序列58529,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。 publicvoidSort(int[]list) { //外层循环数组 for(inti=0;i { //初始第一个值为最小值 min=i; //内层循环,从外层循环的数组元素的后一个元素开始 for(intj=i+1;j { //找到最小的那个元素 if(list[j] min=j; } //把最小的元素放到数组的最前面,然后后面的元素继续循环 intt=list[min]; list[min]=list[i]; list[i]=t; } } (3)插入排序 插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。 当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。 比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。 如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。 所以插入排序是稳定的。 publicstaticvoidinsertSort(int[]temp) { intlength=temp.length; for(inti=1;i { inttempNo=temp[i]; for(intj=0;j { if(tempNo { for(intk=i;k>j;k--)//将其遍历数和比较数之间的数依次向后移动一位 temp[k]=temp[k-1]; temp[j]=tempNo; }}}} (4)快速排序 快速排序有两个方向,左边的i下标一直往右走,当a[i]<=a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。 而右边的j下标一直往左走,当a[j]>a[center_index]。 如果i和j都走不动了,i<=j,交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。 在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为53343891011,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序不是一个稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。 namespacetemp { publicclassQuickSort { /// ///排序 /// /// /// /// privatestaticvoidSort(int[]numbers,intleft,intright) { //左边索引小于右边,则还未排序完成 if(left { //取中间的元素作为比较基准,小于他的往左边移,大于他的往右边移 intmiddle=numbers[(left+right)/2]; inti=left-1; intj=right+1; while(true) { while(numbers[++i] while(numbers[--j]>middle); if(i>=j) break; Swap(numbers,i,j); } Sort(numbers,left,i-1); Sort(numbers,j+1,right); } } /// ///交换元素值 /// /// /// /// privatestaticvoidSwap(int[]numbers,inti,intj) { intnumber=numbers[i]; numbers[i]=numbers[j]; numbers[j]=number; } publicstaticvoidMain() { int[]max={6,5,2,9,7,4,0}; Sort(max,0,max.Length-1); StringBuildertemp=newStringBuilder(); for(inti=0;i { temp.Append(max[i].ToString()+","); } Console.WriteLine(temp.ToString().Substring(0,temp.Length-1)); Console.ReadLine(); }}} (5)归并排序 归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。 所以,归并排序也是稳定的排序算法。 //归并排序 publicvoidMergeSort(intlow,inthigh,int[]a) { intmid,i,j,k; int[]b=newint[high+1]; if(low>=high) { return; } mid=(low+high)/2; MergeSort(low,mid,a); MergeSort(mid+1,high,a); i=low; j=mid+1; k=low; while((i<=mid)&&(j<=high)) { if(a[i]<=a[j]) { b[k]=a[i]; i++; } else { b[k]=a[j]; j++; } k++; } while(j<=high)//如果第二个中仍然有某些元素追加到新列表的子列表 { b[k]=a[j]; j++; k++; } while(i<=mid)//如果在第一个子列表中仍然有一些元素将它们追加到新类别中 { b[k]=a[i]; i++; k++; } for(intii=low;ii<=high;ii++) { a[ii]=b[ii]; } } publicvoiddisplay(int[]a) { intn=a.Length; Console.WriteLine("排序后的数据: "); for(inti=0;i { Console.WriteLine(a[i]); } } } (6)基数排序 基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。 有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。 基数排序基于分别排序,分别收集,所以基数排序是稳定的排序算法。 (7)希尔排序(shell) 希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。 所以,希尔排序的时间复杂度会比o(n^2)好一些。 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。 usingSystem; publicclassShellSorter { publicvoidSort(int[]list) { intinc; for(inc=1;inc<=list.Length/9;inc=3*inc+1); for(;inc>0;inc/=3) { for(inti=inc+1;i<=list.Length;i+=inc) { intt=list[i-1]; intj=i; while((j>inc)&&(list[j-inc-1]>t)) { list[j-1]=list[j-inc-1]; j-=inc; } list[j-1]=t; } } } } publicclassMainClass { publicstaticvoidMain() { int[]iArrary=newint[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47}; ShellSortersh=newShellSorter(); sh.Sort(iArrary); for(intm=0;m<=13;m++) Console.WriteLine("{0}",iArrary[m]); Console.ReadKey(); } } (8)堆排序 我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。 在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。 但当为n/2-1,n/2-2,...1这些个父节点选择元素时,就会破坏稳定性。 有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。 所以,堆排序不是稳定的排序算法。 #region堆 /// ///建成大堆 /// /// /// /// voidHeapAdjust(int[]arr,inti,intlength) { intchild=2*i+1;//左节点 inttemp=arr[i];//中间变量保存当前根节点 while(child { //如果有右节点,判断是否大于左节点 if(child child++; //双亲节点大于子节点 if(temp>=arr[child]) break;//不需调整,结束调整 arr[i]=arr[child];//双亲结点值设置为大的子节点值 i=child; child=2*i+1; } arr[i]=temp; } publicvoidHeap(int[]arr) { //第一次创建大堆 for(inti=arr.Length/2-1;i>=0;i--) { HeapAdjust(arr,i,arr.Length); } //元素位置调换 for(inti=arr.Length-1;i>0;i--) { //堆顶与当前堆的最后一个堆元素交换位置 inttmp=arr[0]; arr[0]=arr[i]; arr[i]=tmp; //将剩下的无序堆部分重新建堆处理 HeapAdjust(arr,0,i); foreach(intvinarr) { Console.Write(v.ToString()+""); } Console.WriteLine(""); } } #endregion 综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。 还有一些排序算法我没有进行
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最新 整理 c# 排序 方法