常用排序算法简介与java实现(冒泡、插入、选择、希尔、归并、快排)

本文介绍六大常用算法的基本思路,以及相应的java函数实现。
本文的eclipse工程源代码可到以下链接下载:
http://download.csdn.net/detail/nostandby/9639511

下面将按照以下顺序进行介绍:
1、冒泡排序、冒泡排序的两种改进。
2、插入排序。
3、选择排序。
4、希尔排序。
5、归并排序。
6、快速排序。

1、冒泡排序:
相邻两个元素进行比较,如果反序就交换

	public void bubbleSort1(List<Integer> nums) {
		for (int i = nums.size(); i > 0; i--) {
			for (int j = 0; j < i - 1; j++) {
				if (nums.get(j).intValue() > nums.get(j + 1).intValue()) {
					swap(nums, j, j + 1);
				}
			}
		}
	}

冒泡排序改进1:
如果某一轮排序过程中没有发生交换,说明所有数据都已经有序,排序可以停止。

	public void bubbleSort2(List<Integer> nums) {
		boolean continueflag = true;
		for (int i = nums.size(); continueflag && i > 0; i--) {
			continueflag = false;
			for (int j = 0; j < i - 1; j++) {
				if (nums.get(j).intValue() > nums.get(j + 1).intValue()) {
					swap(nums, j, j + 1);
					continueflag = true;
				}
			}
		}
	}

冒泡排序改进2:
在改进1的基础上,记录每一轮停止时的索引,这个索引表明:该索引之后的元素都已排好。
那么下一轮到这一位置停止即可

	public void bubbleSort3(List<Integer> nums) {
		int flag;
		for (int i = nums.size(); i > 0; i = flag) {
			flag = 0;
			for (int j = 0; j < i - 1; j++) {
				if (nums.get(j).intValue() > nums.get(j + 1).intValue()) {
					swap(nums, j, j + 1);
					flag = j + 1;
				}
			}
		}
	}

2、插入排序
思想:将一个元素插入到一个有序序列中。
实现思路是:从索引为1 的位置遍历“数组”,将每个元素插入到它前面的有序序列中。
理解它的关键在于:待插入元素之前的元素都是有序的。

	public void insertionSort(List<Integer> nums) {
		int length = nums.size();
		for (int i = 1; i < length; i++) {
			for (int j = i; j > 0 && nums.get(j - 1).intValue() > nums.get(j).intValue(); j--) {
				swap(nums, j, j - 1);
			}
		}
	}

3、选择排序
思想:
(1)、从待排序列中先找到最小的元素,放到第一个位置。
(2)、再从剩余元素中找最小的,放到第二个位置。……
(3)、以此类推,直到所有元素都找到了自己的位置。
选择排序是固定位置,找元素;冒泡排序和插入排序是固定元素找位置。

	public void selectionSort(List<Integer> nums) {
		for (int i = 0; i < nums.size(); i++) {
			int lowindex = i;
			for (int j = i + 1; j < nums.size(); j++) {
				if (nums.get(j).intValue() < nums.get(lowindex).intValue()) {
					lowindex = j;
				}
			}
			swap(nums, i, lowindex);
		}
	}

4、希尔排序(缩小增量排序)
可以认为是插入排序的一种变形。
思路:
先将整个待排元素序列分割成若干子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序
然后依次缩减增量再进行排序
待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序(增量为1)。
其时间复杂度为O(n3/2),要好于直接插入排序的O(n2)

	public void shellSort(List<Integer> nums) {
		int length = nums.size();
		for (int i = length / 2; i > 2; i /= 2) {
			for (int j = 0; j < i; j++) {
				inssort(nums, i);
			}
		}
		inssort(nums, 1);
	}

	private void inssort(List<Integer> nums, int incr) {
		for (int i = incr; i < nums.size(); i += incr) {
			for (int j = i; j >= incr && nums.get(j - incr).intValue() > nums.get(j).intValue(); j -= incr) {
				swap(nums, j, j - incr);
			}
		}
	}

5、归并排序
分而治之,之后合并

	public void mergeSort(List<Integer> nums) {
		mergeSort(nums, 0, nums.size() - 1);
	}

	public void mergeSort(List<Integer> nums, int start, int end) {
		if (start == end)
			return;
		int mid = (start + end) / 2;
		mergeSort(nums, start, mid);
		mergeSort(nums, mid + 1, end);
		List<Integer> temp = new LinkedList<Integer>();
		for (int i = start; i <= end; i++) {
			temp.add(new Integer(nums.get(i).intValue()));
		}
		int i1 = 0, i2 = mid - start + 1;
		for (int curr = start; curr <= end; curr++) {
			if (i1 == mid + 1)
				nums.set(curr, temp.get(i2++));
			else {
				if (i2 > end - start)
					nums.set(curr, temp.get(i1++));
				else {
					if (temp.get(i1).intValue() < temp.get(i2).intValue())
						nums.set(curr, temp.get(i1++));
					else
						nums.set(curr, temp.get(i2++));
				}
			}
		}
	}

6、快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。时间复杂度为O(nlogn)

	public void qsort(List<Integer> nums) {
		qsort(nums, 0, nums.size() - 1);
	}

	public void qsort(List<Integer> nums, int start, int end) {
		if (start > end)
			return;
		int q = partition(nums, start, end);
		qsort(nums, start, q - 1);
		qsort(nums, q + 1, end);
	}

	private int partition(List<Integer> nums, int start, int end) {
		int keyIndex = end;
		int left = start, right = end - 1;
		while (left < right) {
			while (left < right && nums.get(left).intValue() < nums.get(keyIndex).intValue())
				left++;
			while (left < right && nums.get(right).intValue() > nums.get(keyIndex).intValue())
				right--;
			swap(nums, left, right);
		}
		swap(nums, left, keyIndex);
		return left;
	}

关于堆排序,桶排序,计数排序,基数排序等其他排序,时间问题,笔者目前还没有写出源代码。

以上内容仅代表笔者个人理解。如有错误欢迎交流指正。

参考资料:
1、《数据结构与算法分析(C++版)》
2、《算法导论》
3、http://www.open-open.com/lib/view/open1420372620468.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值