最新整理c#排序方法.docx

上传人:b****5 文档编号:7263846 上传时间:2023-01-22 格式:DOCX 页数:10 大小:19.52KB
下载 相关 举报
最新整理c#排序方法.docx_第1页
第1页 / 共10页
最新整理c#排序方法.docx_第2页
第2页 / 共10页
最新整理c#排序方法.docx_第3页
第3页 / 共10页
最新整理c#排序方法.docx_第4页
第4页 / 共10页
最新整理c#排序方法.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

最新整理c#排序方法.docx

《最新整理c#排序方法.docx》由会员分享,可在线阅读,更多相关《最新整理c#排序方法.docx(10页珍藏版)》请在冰豆网上搜索。

最新整理c#排序方法.docx

最新整理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

  {

  ///

  ///排序

  ///

  ///待排序数组

  ///数组第一个元素索引Index

  ///数组最后一个元素索引Index

  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模板 > 自然景观

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1