简单排序
- 受我一个小伙伴的影响,开始重学数据结构
算法的设计取决于选定的逻辑结构,算法的实现则依赖于采用的存储结构。
这里写代码片 *静态结构 * 在数据存在期间不会发生变动 : 静态数组。 *动态结构 * 在一定范围内结构的大小可以发生变动:堆栈。
对于每个排序的描述,是我个人的理解,仅供参考。
一个软件系统的框架应建立在数据之上,而不是操作之上
方法声明:
@Override
public void swap(int a[], int i, int j) {
int buf;
buf = a[i];
a[i] = a[j];
a[j] = buf;
}
@Override
public boolean isLess(int a, int b) {
return a < b ? true : false;
}
BubbleSort
气泡排序应该是接触最早的一种,我是在学 C 语言的时候,接触的。
气泡排序:基本思想是通过前后比较交换,思想比较简单。
代码中有接口、注解,统一在文章末尾说明。
程序清单:
不管其他,先抛异常
/**
* 每次在未排序的元素中,第 j 个和第j +1个比较,然后交换
*/
@Override
public void execute(int a[], int min, int high) throws Exception {
int count = 0;
int exch = 0;
for (int i = 0; i < high; i++) {
for (int j = 0; j < high - i - 1; j++) {
if(isLess(a[j+1], a[j])){
swap(a, j + 1, j);
exch++;
}
count++;
}
}
SampleUtil.print_result("This Bubblet Sort Count", a, count, exch);
}
气泡排序实际比较简单,但是我还是调了一遍。 原因:第一层for循环的时候 length 已经是 a.length - 1 了,我想当然的 写了 “<” ,然后我就想 那最后一个元素不就被漏了。 Too young 气泡排序到最后一个已经是有序了。
SelectSort
/**
* 选择排序,有 N 个元素,依次取出余下N-i个元素中最小的,放入第i个位置。
*/
@Override
public void execute(int a[], int min, int high) throws Exception {
int count = 0;
int exch = 0;
high = a.length;
for (int i = 0; i < high; i++) {
min = i;
for (int j = i + 1; j < high; j++) {
if (isLess(a[j], a[min])) {
min = j;
exch++;
}
}
swap(a, i, min);
count++;
}
SampleUtil.print_result("This is Select Sort", a, count, exch);
}
内循环 For 的时候用了 <= ,外循环到最后一个的时候 如果用 < 会漏下一个元素.
很容易很起泡混淆啊,起泡是每一次遍历时前后比较交换。选择是第 i 次 跟 [ i+1 : N ] 比较交换.
QuickSort
快速排序: 看名字 就在知道 速度快
思想是 选取一个枢轴值 pivot 。 从low位置开始检索,当找到大于等于 pivot 的值时,low与high 所指的进行交换;然后开始从high开始检索找到小于等于 pivot 的值时 low与high交换。当low = high 时 基本有序。
上面是我自己理解的,仅供参考
参考代码:
private int partition(int a[], int low, int high) {
int pivot = a[low];
int count = 0, exch = 0;
// initial statues
while (low < high) {
// this block we want to find a number which value smaller than high
// when the express high < pivot is true then high move to low
while (a[high] >= pivot && low < high) {
high--;
count++;
}
if (a[low] != a[high]) {
swap(a, low, high);
exch++;
low++; // once have change , low must smaller than pivot
}
/*
* other way , this block we want to find one which bigger than
* pivot ,so the low continue move to high until the number bigger
* than pivot
*/
while (a[low] <= pivot && low < high) {
low++;
count++;
}
if (a[low] != a[high]) {
swap(a, low, high);
exch++;
high--; // the same as ' low ++ '
// SampleUtil.print_result("quick Sort : ", a, count, exch);
}
}
return low;
}
/**
* 选择一个枢轴值,从最高位置(high)开始访问元素,1.找到第一个元素 <= pivot 就与low位置的元素交换,此时交换后low位置的元素 <= pivot,然后 low后移。
* 2. 然后从最低位置访问找到第一个 >= pivot 的元素就与high交换,此时high位置的元素 >= pivot,然后high 前移。
* 分别执行上面两部,直到 low >= hight 两者相遇时退出
*
*/
@Override
public void execute(int a[], int low, int high) throws Exception {
if (low > high) {
// print the result of quick sort
SampleUtil.print_result("quick Sort : ", a, 0, 0);
return;
}
int pivot = partition(a, low, high);
execute(a, low, pivot - 1);
execute(a, pivot + 1, high);
}
调用 partition 方法 分成两个基本有序的序列,然后再向两个基本有序的序列分别调用 partition 方法。当 low > high 时推出递归.
InsertSort
插入排序这么写有点像起泡,但是插入排序是在前 i-1 个已经基本有序的元素中插入,原来的元素后移一个位置。
/**
* 升序:N个元素,每次访问都将第 i 个元素 插入到前 i-1 个元素中的合适位置
*/
@Override
public void execute(int[] a, int low, int end) throws Exception {
int count = 0, exch = 0;
for (int i = 0; i < end; i++) {
for (int j = i; j > 0; j--) {
// 升序
// 如果当前元素比已经有序的小,则比当前元素大的都往后移动
if (a[j] < a[j - 1]) {
swap(a, j, j - 1);// 元素后移会导致覆盖 ,所以用交换 替代
exch = 0;
}
count++;
}
}
SampleUtil.print_result("Insert Sort : ", a, count, exch);
}
测试方法:
上面的每个方法都实现了Sort 接口。接口代码……
package com.foo._Alogrithm.SampleSort;
public interface Sort {
public void execute(int a[], int low, int end) throws Exception;
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring.xml " })
public class JunitTest {
int a[] = { 1, 2, 43, 5, 856, 6, 78, 276, 34, 23, 69, 3, 654, 54, 65, 7, 889 };
// @Autowired
// private QuickSort quickSort;
//
// @Autowired
// private BubbleSort bubbleSort;
//
// @Autowired
// private SelectSort selectSort;
// Sort sort = new SelectSort();
// Sort sort = new BubbleSort();
Sort sort = new QuickSort();
@Test
public void test() {
try {
sort.execute(a, 0, a.length - 1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
mark 完了……
为什么用注解?
用注入的嘛 我就不用都去new 一个对象了。但是后面感觉,每次都要加@Autowired,好麻烦;后面就都实现了一个接口。多态嘛…… 然后省事二点儿……