一些排序算法(Java 实现)

1、插入排序

在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的, 现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。

public static void insertSort(int[] a) {
	int len = a.length;// 数组长度
	int insertNum;// 要插入的数
	for (int i = 1; i < len; i++) {
		insertNum = a[i];
		int j = i - 1;// 序列元素个数
		while (j >= 0 && a[j] > insertNum) {// 从后往前循环,将大于insertNum的数向后移动
			a[j + 1] = a[j];// 元素向后移动
			j--;
		}
		a[j + 1] = insertNum;// 找到位置,插入当前元素
	}
}

2、选择排序

简单选择排序:
遍历整个序列,将最小的数放在最前面。
遍历剩下的序列,将最小的数放在最前面。
重复第二步,直到只剩下一个数。

public static void selectSort(int[] a) {
		int len = a.length;
		for (int i = 0; i < len; i++) {
			int value = a[i];
			int position = i;
			for (int j = i + 1; j < len; j++) {// 找到最小的值和位置
				if (a[j] < value) {
					value = a[j];
					position = j;
				}
			}
			a[position] = a[i];
			a[i] = value;
		}
	}

3、冒泡排序

设置开始比较的位数,和结束的位数。
两两比较,将最小的放到前面去。
重复1、2步,直到循环次数完毕。

public static void bubbleSort(int[] a) {
	for(int i=0;i<a.length;i++) {
		for(int j=i+1;j<a.length;j++) {
			if(a[j]<a[i])swap(a,i,j);
		}
	}
}

/**
 * 交换数
 */
 private static void swap(int[] item, int i, int j) {
	item[i] = item[i]^item[j];
	item[j] = item[i]^item[j];
	item[i] = item[i]^item[j];
}

4、快速排序(递归方式)

选择要排序的数组里面的一个基值p(关于基值的选法,这里默认取第一个),小于p的数放在左边,大于p的数放在右边。
递归的将p左边和右边的数都按照第一步进行,直到不能递归。

public static void quickSort(int[] a,int start,int end) {
		if(start >= end)return ;
		int baseNum=a[start];
		int l=start;
		int r=end;
		do {
			while(a[l]<baseNum&&l<end) {
				l++;
			}
			while(a[r]>baseNum&&r>start) {
				r--;
			}
			if(l<=r) {
				if(l<r){
					System.out.println("当前基值:"+baseNum+" 交换位置"+l+":"+a[l]+"和"+r+":"+a[r]);
					swap(a,l,r);
					System.out.println("交换结果:"+Arrays.toString(a));
				}
				l++;
				r--;
			}
		}while(l<r);
		if(r>start)quickSort(a,start,r);
		if(l<end)quickSort(a,l,end);
	}

5、希尔排序(Sheel排序)

将数的个数设为n,取奇数k=n/2,将下标差值为k的数分为一组,构成有序序列。
再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。
重复第二步,直到k=1执行简单插入排序。

	public static void sheelSort(int[] a) {
		int len = a.length;
		while (len != 0) {
			len = len / 2;
			for (int i = 0; i < len; i++) {// 分组
				for (int j = i + len; j < a.length; j += len) {// 元素从第二个开始
					int k = j - len;// k为有序序列最后一位的位数
					int temp = a[j];// 要插入的元素
					while (k >= 0 && temp < a[k]) {// 从后往前遍历
						a[k + len] = a[k];
						k -= len;// 向后移动len位
					}
					a[k + len] = temp;
				}
			}
		}
	}

6、堆排序

将序列构建成大顶堆。
将根节点与最后一个节点交换,然后断开最后一个节点。
重复第一、二步,直到所有节点断开。

	public static void heapSort(int[] a) {
		//从最后一个非叶子节点开始,建堆
		for (int i = a.length / 2 - 1; i >= 0; i--) {
			adjustHeap(a, i, a.length);
		}
		// 下面,开始排序逻辑
		for (int j = a.length - 1; j > 0; j--) {
			// 元素交换
			// 说是交换,其实质就是把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
			swap(a, 0, j);
			// 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
			// 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因
			// 而这里,实质上是自上而下,自左向右进行调整的
			adjustHeap(a, 0, j);
		}
	}
	private static void adjustHeap(int[] a, int i, int length) {
		// 先把当前元素取出来,因为当前元素可能要一直移动
		int temp = a[i];
		// 可以参照sort中的调用逻辑,在堆建成,且完成第一次交换之后,实质上i=0;也就是说,是从根所在的最小子树开始调整的
		// 接下来的讲解,都是按照i的初始值为0来讲述的
		// 这一段很好理解,如果i=0;则k=1;k+1=2
		// 实质上,就是根节点和其左右子节点记性比较,让k指向这个不超过三个节点的子树中最大的值
		// 这里,必须要说下为什么k值是跳跃性的。
		// 首先,举个例子,如果a[0] >
		// a[1]&&a[0]>a[2],说明0,1,2这棵树不需要调整,那么,下一步该到哪个节点了呢?肯定是a[1]所在的子树了,
		// 也就是说,是以本节点的左子节点为根的那棵小的子树
		// 而如果a[0}<a[2]呢,那就调整a[0]和a[2]的位置,然后继续调整以a[2]为根节点的那棵子树,而且肯定是从左子树开始调整的
		// 所以,这里面的用意就在于,自上而下,自左向右一点点调整整棵树的部分,直到每一颗小子树都满足大根堆的规律为止
		for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
			//2*i+1是i节点的左子节点坐标
			// 让k先指向子节点中最大的节点
			if (k + 1 < length && a[k] < a[k + 1]) {
				k++;
			}
			// 如果发现子节点更大,则进行值的交换
			if (a[k] > temp) {
				swap(a, i, k);
				// 下面就是非常关键的一步了
				// 如果子节点更换了,那么,以子节点为根的子树会不会受到影响呢?
				// 所以,循环对子节点所在的树继续进行判断
				i = k;
				// 如果不用交换,那么,就直接终止循环了
			} else {
				break;
			}
		}
	}

新人瞎整理的,原理后面在补充。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值