快面试了,回顾一下基础知识。。。。名字乱取的。不对的地方请指正,有问题请提出。Many 3KS
【排序分类】:
交换排序: 包括冒泡排序,快速排序。
选择排序: 包括直接选择排序,堆排序。
插入排序: 包括直接插入排序,希尔排序。
合并排序: 合并排序。
【冒泡排序VS快排】
要达到冒泡的效果,我们就要把一组数字竖起来看,数字大的往下沉。
第一步: 我们拿40跟20比,不用交换。
第二步: 然后向前推一步,就是拿20跟30比,交换。
第三步:拿交换后的20跟10比,不用交换。
第四步:拿10跟50比,进行交换。
最后,我们经过一次遍历,把数组中最小的数字送上去了,看看,我们向目标又迈进了一步。
写个代码来测试下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { for (int i = 1; i < 5; i++) { Listlist = new List (); for (int j = 0; j < 2000; j++) { Thread.Sleep(1); list.Add(new Random((int)DateTime.Now.Ticks).Next(0, 10000)); } Console.WriteLine("\n第" + i + "次比较:"); Stopwatch watch = new Stopwatch(); watch.Start(); var result = list.OrderBy(single => single).ToList(); watch.Stop(); Console.WriteLine("\n快速排序耗费时间:" + watch.ElapsedMilliseconds); Console.WriteLine("输出前是十个数:" + string.Join(",", result.Take(10).ToList())); watch.Start(); result = BubbleSort(list); watch.Stop(); Console.WriteLine("冒泡排序耗费时间:" + watch.ElapsedMilliseconds); Console.WriteLine("输出前是十个数:" + string.Join(",", result.Take(10).ToList())); Console.WriteLine("----------------------------------------------------------"); } Console.Read(); } static List BubbleSort(List list) { for (int i = 0; i < list.Count-1; i++) { for (int j = list.Count - 1; j>i ; j--) { if(list[j-1]>list[j]) { list[j - 1] = list[j - 1] ^ list[j]; list[j] = list[j - 1] ^ list[j]; list[j - 1] = list[j - 1] ^ list[j]; } } } return list; } } }
冒泡的速度灰常不给力。
【快速排序】
快排的速度咋就这么快捏?查点资料看看~
基本思想是:通过一趟排序将要排序的书记局分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后递归。
soga。。再参考下别人的例子,这也叫挖坑填数+分治法
1.先挖出来一个数字作为base基准
2.从后向前找一个比这个数字小的数,填到这个坑里。j--
3.这个数字被挖走,留坑。再从前向后找一个比base大的数,填到这个坑。i++
4.重复2,3直到i,j重合
比如下面的例子,7个数字【初始条件 base=5; i=1; j=7】
5 | 3 | 1 | 2 | 7 | 9 | 4 |
=>【条件 base=5; i=1; j=7】
从j向i找<base的数字4,得到
4 | 3 | 1 | 2 | 7 | 9 | 坑 |
=>【条件 base=5; i++=2; j=7】
从i向j找>base的数字7,得到
4 | 3 | 1 | 2 | 坑 | 9 | 7 |
=>【条件 base=5; i=2; j--=6】
从j向i找<base的数字2
4 | 3 | 1 | 坑 | 2 | 9 | 7 |
=>【条件 base=5; i++=3; j=6】
从i向j找>base的数字,木有=>【条件 base=5; i=3; j--=5】
从j向i找<base的数字2
4 | 3 | 1 | 2 | 坑 | 9 | 7 |
这样,ij就重合了,于是坑=5,坑左边的比5小,坑右边的比5大
最后,以5为分界线,重复上面的操作,即迭代。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace 快速排序算法 { class Program { static void Main(string[] args) { for (int i = 1; i < 5; i++) { Listlist = new List (); for (int j = 0; j < 200; j++) { Thread.Sleep(1); list.Add(new Random((int)DateTime.Now.Ticks).Next(0, 10000)); } Console.WriteLine("\n第" + i + "次比较:"); Stopwatch watch = new Stopwatch(); watch.Start(); var result = list.OrderBy(single => single).ToList(); watch.Stop(); Console.WriteLine("\n自带快速排序耗费时间:" + watch.ElapsedMilliseconds); Console.WriteLine("输出前是十个数:" + string.Join(",", result.Take(10).ToList())); watch.Start(); result = QuickSort(list.ToArray (),0,list.Count-1); watch.Stop(); Console.WriteLine("我的快速排序耗费时间:" + watch.ElapsedMilliseconds); Console.WriteLine("输出前是十个数:" + string.Join(",", result.Take(10).ToList())); Console.WriteLine("----------------------------------------------------------"); } Console.Read(); } static List QuickSort(int[] list, int left, int right) { if (left < right) { //Swap(list[left], list[(left + right) / 2]); //将中间的这个数和第一个数交换 参见注1 int i = left, j = right, x = list[left]; while (i < j) { while (i < j && list[j] >= x) // 从右向左找第一个小于x的数 j--; if (i < j) list[i++] = list[j]; while (i < j && list[i] < x) // 从左向右找第一个大于等于x的数 i++; if (i < j) list[j--] = list[i]; } list[i] = x; QuickSort(list, left, i - 1); // 递归调用 QuickSort(list, i + 1, right); } return list.ToList (); } } }
则是结果。发现差不多,但是如果将list弄的再长点,又会有差距了。
冒泡的时间复杂度为: 0(n) - 0(n^2)
快排的时间复杂度为:
平均复杂度: N(logN)
最坏复杂度: 0(n^2)
作者:石世特
出处:http://www.cnblogs.com/TivonStone/
希望本文对你有所帮助,想转随便转,心情好的话给我的文章留个链接.o(. .)o