java基本排序算法(除桶排序)

java实现常用的排序算法。
相应的思路再注释中。

class Sort{
	//排序算法总结
	
	/*
	*	1.直接插入排序
	*	序列中前n个数为已排序序列,将第n+1个数插入到前n个数的适当位置中。
	*/
	public int[] insertSort(int[] arr){
		int insertNum;
		//n个数的序列进行n-1次插入。
		for(int i=1; i<arr.length; i++){
			insertNum = arr[i];
			//前i-1个数已经排好序,则将用第i个数和第j=i-1个数比较。如果大于第j个数,则将第j个数后移1位。
			//并将待排序的数插入第j位。之后开始和第j-1位比较,循环比较到第一位。
			for(int j=i-1; j>=0 && insertNum < arr[j]; j--){
				arr[j+1] = arr[j];
				arr[j] = insertNum;
			}
		}
		return arr;
	}
	
	/*
	*	2.希尔排序
	* 	先将序列按增量d分为若干子序列,然后对子序列使用直接插入排序。
	*	然后减小增量d再进行一次直接插入排序。
	*	直至d=0进行一趟直接插入排序
	*/
	public int[] shellSort(int[] arr){
		int d = arr.length;
		while(d != 0){
			//对增量循环,对折增量
			d = d/2;
			for(int i=0; i<d; i++){
				//d的大小就相当与子序列的组数。循环d,可认为是在循环组数
				for(int j=i+d; j<arr.length; j+=d){
					//从这里开始,就是对每一组开始进行直接插入排序。
					//代码没区别,只是循环增量,还有在循环的起始位置上都要加上d。
					//同时,最外层循环从每组第一个元素开始。那就是组数i加上增组数d
					int s;
					int insertNum = arr[j];
					for(s=j-d; s>=0 && arr[s]>insertNum; s-=d){
						arr[s+d] = arr[s];
						arr[s] = insertNum;
					}
				}
			}
		}
		return arr;
	}
	
	/*
	*	3.简单选择排序
	*	遍历整个序列将最小的数放到第一个。
	*	遍历剩下的序列,将最小的放在最前面
	*	重复上述步骤
	*/
	public int[] selectSort(int[] array){
		for(int times=array.length-1; times>0; times--){
			for(int idx=0; idx<times; idx++){
				if(array[idx]>array[times]){
					int tmp = array[times];
					array[times] = array[idx];
					array[idx] = tmp;
				}
			}
		}
		return array;
	}

	
	
	/*
	*	4.堆排序
	*	堆顶元素为最大值(大根堆)将堆顶元素输出,之后用堆中最后一个元素代替堆顶
	*	再对堆进行筛选排序。调整过后输出新的堆顶重复上述步骤。(代码回头补吧)
	*/
	public int[] heapSort(int[] arr){
		//一下这步操作,堆的构建就已经完成。
		for(int i=arr.length-1; i>=0; i--){
			percDown(arr, i, arr.length-1);
		}
		print("【构建堆已完成】 构建结果:");
		printArr(arr);
		
		//构建堆完成后,我们将堆顶元素放置到末尾,并将堆尾放到队首并重新构建堆
		for(int j=arr.length-1; j>0; j--){
			print("====================in=====================\n");
			//交换堆顶和堆尾元素
			//print("【此时的堆顶为:"+arr[0]+" 此时的堆尾为:"+arr[j]+"】\n");
			int temp = arr[0];
			arr[0] = arr[j];
			arr[j] = temp;
			print("【交换堆顶和堆尾元素后数组为:】");
			printArr(arr);
			//刨除堆尾元素重新构建堆
			percDown(arr, 0, j-1);
			print("【重新构建后数组为:】");
			printArr(arr);
		}
		print("最终结果!!=》");
		return arr;
	}
	/*
	*	下滤操作:先比较根节点的孩子,选出较小的节点,之后将根节点和其比较
	*	根节点小则交换	
	*	@param arr=>需要被构建堆的数组
	*	@param node=>开始下滤的根节点
	*	@param len=>下滤树的大小
	*/
	public void percDown(int[] arr, int node, int len){
		print("数组长度为:"+len+"\n");
		int elem = arr[node];
		while(node<len && 2*node+1<len){
			int child = node*2+1;
			print("当前根节点为:"+node+"\n 左孩子节点为:"+child+"\n");
			if(child != len && arr[child+1] < arr[child]){
				child++;
				print("右孩子节点"+child+"值更小\n");
			}
				
			
			if(arr[child]<elem){
				arr[node]=arr[child];
			}else
				//此处的break很有意思。意味着当根节点不比子节点大时,就需要跳出循环
				//否则空穴会跳到下一个语句则循环外的赋值就出问题了。
				break;
			node = child;
		}
		arr[node]=elem;
	}

	
	/*
	*	5.冒泡排序
	*	两个元素两两比较,将大元素向下沉,小元素向上浮
	*/
	public int[] bubbleSort(int[] arr){
		for(int i=0; i<arr.length; i++){
			/*
			*	下面的循环当中是两两比较的过程,并把大元素不断往后放。
			*	因为是元素一个一个向后移,所以上一轮比较的大值又参与下一轮比较,
			*	这样在一轮循环的最后就是序列中的最大值。
			*	已经得到了整个序列中的最大值,所以最后以为就不需要比较了。
			*	因此,内循环的边界条件需要用数组长度减去i(已经循环的次数,循环了几次就有几个最大值,也就是已经排好序的个数)
			*/
			for(int j=0; j<arr.length-1-i; j++){
				if(arr[j]>arr[j+1]){
					int temp = arr[j+1];
					arr[j+1] = arr[j];
					arr[j] = temp;
				}
			}
			printArr(arr);
		}
		return arr;
	}
	
	/*
	*	6.快速排序
	*/
	//快速排序入口
	public int[] quickSort(int[] arr){
		QKSort(arr, 0, arr.length-1);
		return arr;
	}
	//快速排序过程
	public void QKSort(int[] arr, int head, int tail){
		if(head<tail){
			//调用一趟排序过程。之后返回
			int position = quickSortOne(arr, head, tail);
			QKSort(arr, head, position-1);
			QKSort(arr, position+1, tail);
		}
	}
	//此函数为快速排序的一趟排序过程
	public int quickSortOne(int[] arr, int head, int tail){
		int base = arr[head];
		/*
		*	这里选最低位为基准数。那么循环中,就要让高位先往左走,在让低位往右走。
		*	因为低位为基准数。则base存储了低位变量,而如果低位先往右走,但高位上目前没有空位则不方便交换
		*	否则还要添加变量。当退出循环时,head=tail。便将base值放入其中。
		*/
		while(head<tail){
			while(head<tail && arr[tail]>base)
				tail--;
			if(head<tail){
				arr[head]=arr[tail];
				head++;
			}
			while(head<tail && arr[head]<base)
				head++;
			if(head<tail){
				arr[tail]=arr[head];
				tail--;
			}
		}
		arr[head]=base;
		print("quick sort");
		printArr(arr);
		return head;
	}
	
	/*
	*	7.归并排序
	*/
	//归并排序入口
	public int[] mergeSort(int[] arr){
		int[] temp = new int[arr.length];
		mergeSort(arr, temp, 0, arr.length-1);
		return arr;
	}
	public void mergeSort(int[] arr, int [] temp, int left, int right){
		if(left < right){
			//这里开始将排序问题递归分解。
			int center = (left+right)/2;
			mergeSort(arr, temp, left, center);
			mergeSort(arr, temp, center+1, right);
			//这里调用归并函数开始合并。
			merge(arr, temp, left, center+1, right);
		}
		if(left == right)
			merge(arr, temp, left, left, left);
	}
	
	public void merge(int[] arr, int[] temp, int leftStart, int rightStart, int rightEnd){
		print("============================================");
		print("beginArr = ");
		printArr(arr);
		int leftEnd = rightStart-1;
		int tempArrPos = leftStart;
		int numElems = rightEnd-leftStart+1;
		print("leftStart = "+leftStart+" leftEnd = "+leftEnd+" rightStart = "+rightStart+" rightEnd = "+rightEnd+"\n");
		
		
		//主循环,合并元素
		while(leftStart<=leftEnd && rightStart <= rightEnd){
			print("in main \n");
			if(arr[leftStart] < arr[rightStart]){
				print("left in \n");
				temp[tempArrPos++] = arr[leftStart++];
			}else{
				temp[tempArrPos++] = arr[rightStart++];
				print("right in \n");
			}
		}
		
		//跳出上面的循环意味着,两个序列中有一个已经全部排好序。只需将剩下的序列依次填充就好
		while(leftStart<=leftEnd){
			temp[tempArrPos++] = arr[leftStart++];
			print("in single left \n");
		}
		while(rightStart <= rightEnd){
			temp[tempArrPos++] = arr[rightStart++];
			print("in single right \n");
		}
		print("tempArr = ");
		printArr(temp);
		//将排好序的数组赋值给原数组
		//temp的长度要比arr小,所以从后往前赋值防止越界
		for(int i=0; i<numElems; i++, rightEnd--){
			arr[rightEnd] = temp[rightEnd];
		}
		print("resArr = ");
		printArr(arr);
	}
	
	
	
	
	public static void main(String[] args){
		Sort s = new Sort();
		int[] val = {43,32,23,13,5,8,14};
		int[] ret = s.heapSort(val);
		printArr(ret);
		
	}
	
	public static void print(Object o){
		System.out.print(o);
	}
	
	public static void printArr(int[] arr){
		String str = "[";
		for(int i=0; i<arr.length; i++){
			str += arr[i]+",";
		}
		str = str.substring(0, str.length()-1);
		print(str+"]");
		System.out.println();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值