各种排序算法
2016-04-12 18:08
441 查看
快速排序
快速排序作为复杂排序中最好用的排序算法,作为程序员是必须要掌握的。
先说说排序算法的思路,我们对照着下图慢慢说。
比如我们有一个数组:
我们随便选择一个值为基准数X,我们这里选择0位置的数字6,X=6。然后我们创建两个游标 i和j 。因为我们是要对整个数组进行排序,那么我们就给游标一个初始值: i = 0 ,j = 6 。
初始化的工作完成了,接下来是排序的核心内容了。
第一步,把比基准数大的数放在右边,把比基准数小的数放左边。
我们从右边开始向左移动游标j,选择一个比基准数小的数放到基准数的位置。当j为5的时候,发现2小于等于6。
接下来我们从左边开始向右移动游标i,选择一个比基准数大的数放到之前空去来的位置。当i移动到2的时候,发现7大于等于6。
。我们发现了当j为3的时候,9大于等于6。
第二步,我们把基准数左边和右边都提取出来,得到两个小的集合。
和
我们把这两个数组分别使用第一步的方法,接着分下去。分到的集合继续分下去,直到不能分下去为止。因为这种分割的方法,我称它为二分法。
我找到了一幅图,可能会比较形象,容易大家理解。
想来大家对快速排序的思路比较清晰了。我们使用代码来实现这个思路:
怎么样?是不是很简单!大家去试试吧!
直接插入排序
还是先讲讲思路,我们从数组第二个数据开始遍历,将这个数和他前面的数进行比较,如果前面的数大于这个数,就将前面数的位置向后移动一位,不大于就将这个数放到前面位置的后面一位(原地不动),遍历完了没有插入就放到角标为0的位置。
思路说的有点绕,我们以一个实例来详细说明。
我们从角标为1的位置,这个位置的数是4,拿他和前面比较,6大于4,把6移动到角标1的位置,然后继续遍历,遍历完没有插入,把这个数放到角标为0的位置。
我们选择角标为3的数3,拿它和前面的数比较,3小于4、6、7,7、6、4依次向后移动一位,3没有插入,我们把他放到角标为0的位置。
冒泡排序
先说说思路。从右往左相邻的两个数两两比较,把小的数放前,一次循环,把最小的数放到最前面。然后将除了最前面一个数从右至左两两比较,确定第二小的数,这样依次从前往后确定数的位置,实现排序。我们来看图说话:
从角标为5的位置开始,1、3比较,1小,1放前面,然后1、6比较,1小,放前面,依次这样,将1放到最前面。就实现了最小值放最前面。
我们用代码来实现这个思路:
来看一张图便于理解冒泡排序:
简单选择排序
简单选择排序和冒泡排序有点相似,都是通过循环来找到最大数/最小数,然后找到第二大/小的数,不同的是冒泡排序是在不断的交换来事件排序,而选择排序是直接在里面找到我们想要的数。
以0号位置的数42为基准数,假设他为最小值,遍历它后面的数,如果有比他小的数就记录下来,和0号位置的42交换,那么就找到了第一小的数。接着从1号位置开始,假设为最小值,遍历后面的数找到第二小的数,以此类推实现排序。
我们用代码来实现这种排序:
简单选择排序示意图:
快速排序作为复杂排序中最好用的排序算法,作为程序员是必须要掌握的。
先说说排序算法的思路,我们对照着下图慢慢说。
比如我们有一个数组:
角标 0 1 2 3 4 5 6 数组 6 4 7 3 9 2 8
我们随便选择一个值为基准数X,我们这里选择0位置的数字6,X=6。然后我们创建两个游标 i和j 。因为我们是要对整个数组进行排序,那么我们就给游标一个初始值: i = 0 ,j = 6 。
初始化的工作完成了,接下来是排序的核心内容了。
第一步,把比基准数大的数放在右边,把比基准数小的数放左边。
我们从右边开始向左移动游标j,选择一个比基准数小的数放到基准数的位置。当j为5的时候,发现2小于等于6。
角标 0 1 2 3 4 5 6 数组 2 4 7 3 9 ? 8
接下来我们从左边开始向右移动游标i,选择一个比基准数大的数放到之前空去来的位置。当i移动到2的时候,发现7大于等于6。
角标 0 1 2 3 4 5 6 数组 2 4 ? 3 9 7 8然后我们又由右向左移动j,找一个大于6的值。是不是有种荡秋千的感觉
。我们发现了当j为3的时候,9大于等于6。
角标 0 1 2 3 4 5 6 数组 2 4 3 ? 9 7 8之后我们向右移动i,当为3的时候,i就和j相等了!我们把基准数赋值给这个‘?’,第一步就完成了!
角标 0 1 2 3 4 5 6 数组 2 4 3 6 9 7 8我们可以发现比基准数小的数在基准数的左边,比基准值大的数在基准数的右边,而基准数的位置就是最终排序结果的位置。
第二步,我们把基准数左边和右边都提取出来,得到两个小的集合。
角标 0 1 2 数组 2 4 3
和
角标 0 1 2 数组 9 7 8
我们把这两个数组分别使用第一步的方法,接着分下去。分到的集合继续分下去,直到不能分下去为止。因为这种分割的方法,我称它为二分法。
我找到了一幅图,可能会比较形象,容易大家理解。
想来大家对快速排序的思路比较清晰了。我们使用代码来实现这个思路:
/// <summary> /// 快速排序 /// </summary> /// <param name="arrayAway">需要排序的集合</param> /// <param name="left">开始位置的角标</param> /// <param name="right">结束位置的角标</param> public void QuickSort( int[] arrayAway, int left, int right) { if (left < right) //左边必须小于右边 { int X = arrayAway[left]; int i = left; int j = right; while (i < j) { //从右至左移动,找到一个比基准数小的数,把这个数放到基准数的位置。 while (i < j) { if (arrayAway[j] <= X) { arrayAway[i] = arrayAway[j]; break; } else { j--; } } //从左至右移动,找到一个比基准数大的数,把这个数放到之前空出的位置(角标为j的位置)上。 while (i < j) { if (arrayAway[i] >= X) { arrayAway[j] = arrayAway[i]; break; } else { i++; } } } //第一步的最后,将基准值放到i=j的位置。 arrayAway[i] = X; //第二步,我们递归这个方法 QuickSort( arrayAway, left, i - 1); QuickSort( arrayAway, i + 1, right); } }
怎么样?是不是很简单!大家去试试吧!
直接插入排序
还是先讲讲思路,我们从数组第二个数据开始遍历,将这个数和他前面的数进行比较,如果前面的数大于这个数,就将前面数的位置向后移动一位,不大于就将这个数放到前面位置的后面一位(原地不动),遍历完了没有插入就放到角标为0的位置。
思路说的有点绕,我们以一个实例来详细说明。
角标 0 1 2 3 4 5 6 数组 6 4 7 3 9 2 8
我们从角标为1的位置,这个位置的数是4,拿他和前面比较,6大于4,把6移动到角标1的位置,然后继续遍历,遍历完没有插入,把这个数放到角标为0的位置。
角标 0 1 2 3 4 5 6 数组 4 6 7 3 9 2 8我们继续选择2号位置的7,将7和前面的数比较,6小于7,那么7的位置不变。
我们选择角标为3的数3,拿它和前面的数比较,3小于4、6、7,7、6、4依次向后移动一位,3没有插入,我们把他放到角标为0的位置。
角标 0 1 2 3 4 5 6 数组 3 4 6 7 9 2 8说到这,其实思路已经很清楚了,也没有再继续啰嗦的必要了。我们使用代码来实现这个思路。
void InsertSort(int[] arrayAway) { for (int i = 1; i < arrayAway.Length; i++ ) { int X = arrayAway[i]; bool flag = false; //将X和前面相比较,如果值大于X,向后移动一位,如果小于,就讲X放到前面值得后一位(也就是当前X的位置) for (int j = i - 1; j >= 0;j-- ) { if (arrayAway[j] > X) { arrayAway[j + 1] = arrayAway[j]; } else { arrayAway[j + 1] = X; flag = true; break; } } if (!flag) arrayAway[0] = X; } }
冒泡排序
先说说思路。从右往左相邻的两个数两两比较,把小的数放前,一次循环,把最小的数放到最前面。然后将除了最前面一个数从右至左两两比较,确定第二小的数,这样依次从前往后确定数的位置,实现排序。我们来看图说话:
从角标为5的位置开始,1、3比较,1小,1放前面,然后1、6比较,1小,放前面,依次这样,将1放到最前面。就实现了最小值放最前面。
我们用代码来实现这个思路:
void BubblingSort(int[] arrayAway) { for (int i = 0; i < arrayAway.Length;i++) { int X = 0; //交换位置的容器 for (int j = arrayAway.Length - 1; j > 0;j--) { //如果前面的大于后面的,就交换位置 if(arrayAway[j-1]>arrayAway[j]){ X = arrayAway[j]; arrayAway[j] = arrayAway[j - 1]; arrayAway[j - 1] = X; } } } }
来看一张图便于理解冒泡排序:
简单选择排序
简单选择排序和冒泡排序有点相似,都是通过循环来找到最大数/最小数,然后找到第二大/小的数,不同的是冒泡排序是在不断的交换来事件排序,而选择排序是直接在里面找到我们想要的数。
以0号位置的数42为基准数,假设他为最小值,遍历它后面的数,如果有比他小的数就记录下来,和0号位置的42交换,那么就找到了第一小的数。接着从1号位置开始,假设为最小值,遍历后面的数找到第二小的数,以此类推实现排序。
我们用代码来实现这种排序:
void SelectSort(int[] arrayAway) { for (int i = 0; i < arrayAway.Length - 1;i++ ) { int min = arrayAway[i]; int minIndex = i; for (int j = i + 1; j < arrayAway.Length;j++) { if(arrayAway[j]<min){ min = arrayAway[j] ; minIndex = j; } } if(minIndex != i){ int temp = arrayAway[i]; arrayAway[i] = arrayAway[minIndex]; arrayAway[minIndex] = temp; } } }
简单选择排序示意图:
相关文章推荐
- JavaScript演示排序算法
- Kinect结合Unity3D引擎开发体感游戏(一)
- 快速排序
- C#快速排序算法实例分析
- 算法之排序算法的算法思想和使用场景总结
- C++快速排序的分析与优化详解
- PHP版本常用的排序算法汇总
- JavaScript实现多种排序算法
- js实现数组冒泡排序、快速排序原理
- php简单实现快速排序的方法
- Java 快速排序(QuickSort)原理及实现代码
- 快速排序和分治排序介绍
- java 算法之快速排序实现代码
- php 地区分类排序算法
- js三种排序算法分享
- Javascript中的常见排序算法
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
- Java实现快速排序算法(Quicktsort)
- Java中的数组排序方式(快速排序、冒泡排序、选择排序)