各种排序的Java实现

package sort;

/**
* @author Administrator
* @version 创建时间:2018年4月12日 上午9:32:48
* @ClassName 类名称
* @Description 类描述
*/


public class Sort {
	private int[] nums= {2,4,6,7,98,0,2,6,9,1};
	//private int[] nums= {5,4,3,2,1};
	public void swap(int[] nums,int i,int j){//交换数组等集合里的元素,引用传递,而非值传递
		int temp;
		temp =nums[i];
		nums[i]=nums[j];
		nums[j]=temp;		
	}
	public void BubbleSort0(int[] nums,int n){//冒泡排序初级版:最最简单的交换排序
		int i,j;
		for(i=0;i<n-1;i++){
			for(j=i+1;j<n;j++){
				if(nums[i]>nums[j])
					swap(nums,i,j);
			}
		}
	}
	
	public void BubbleSort(int[] nums,int n){//冒泡排序
		int i,j;
		for(i=0;i<n;i++){//每一轮比较把最小的放最前面
			for(j=n-1;j>i;j--){//从最后到i两两交换,较小者放在前面,即“冒泡”,注意j是从后往前循环				
				if(nums[j-1]>nums[j])
					swap(nums,j-1,j);
			}
		}	
	}
	
	/*冒泡排序优化,增加标记来减少排序次数,避免因已经有序的情况下的无意义循环判断。*/
	public void BubbleSort2(int[] nums,int n){
		int i,j,flag=1;//flag用于标记是否有交换操作	
		for(i=0;i<n && flag==1;i++){//若flag为0,表示没有发生交换,则退出循环
			flag = 0;//0表示没有交换
			for(j=n-1;j>i;j--){				
				if(nums[j-1]>nums[j]){
					swap(nums,j-1,j);
					flag = 1;//若产生交换,flag置为1
				}
			}
		}
	}
	//选择排序:寻找序列中的最小值,用当前位置的值交换最小值
	public void SelectSort(int[] nums,int n){
		int i,j,min;
		for(i=0;i<n-1;i++){
			min=i;   //将当前下标定义为最小值下标 
			for(j=i+1;j<n;j++){   //循环之后的数据
				if(nums[j]<nums[min]){//如果有小于当前最小值的关键字,将此关键字的下标赋值给min
					min=j;
				}
				if(i!=min)  //若min不等于i,说明找到最小值,交换
					swap(nums,i,min);
			}
		}
	}
	/* 插入排序
	 * 基本思想是在遍历数组的过程中,假设在序号 i (i>=1)之前的元素即 [0..i-1] 都已经排好序,
	 * 本趟需要找到 i 对应的元素 x 的正确位置 k ,并且在寻找这个位置 k 的过程中逐个将比较过的元素往后移一位,
	 * 为元素 x “腾位置”,最后将 k 对应的元素值赋为 x
	 */
	public void InsertSort(int[] nums,int n){
		int i,j,temp;
		for(i=1;i<n;i++){
			//只有当前位置i元素小于已经有序的[0,i-1]中的最大元素nums[i-1]时,才需要进行插入
			if(nums[i]<nums[i-1]){
				temp=nums[i];//存当前位置i的元素,其中[0,i-1]已经有序
				for(j=i;j>0&&nums[j-1]>temp;j--){
					nums[j]=nums[j-1];//从i-1开始遍历到0,比temp大的数后移一位
				}
				nums[j]=temp;//插入到合适的位置
			}		
		}	
	}
	
	/* 希尔排序
	 */
	public void ShellSort(int[] nums,int n){
		int i,j,temp;
		int h = 1; /* 关于步长,取值没有统一标准,必须小于size,最后一次步长要为1 */    
	    for(h = 1;h < n/3;h= 3*h+1);//计算首次步长
		for(;h>0;h=h/3){
			for(i=h;i<n;i++){
				//只有当前位置i元素小于已经有序的[0,i-1]中的最大元素nums[i-h]时,才需要进行插入
				if(nums[i]<nums[i-h]){
					temp=nums[i];//存当前位置i的元素,其中[0,i-1]已经有序
					for(j=i;j>h-1&&nums[j-h]>temp;j=j-h){
						nums[j]=nums[j-h];//从i-h开始遍历到h-1,比temp大的数后移h位
					}
					nums[j]=temp;//插入到合适的位置
				}		
			}
		}		
	}
	/*	 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上),
	 *  即[s..m]中记录的关键字除[s]之外均满足堆的定义 ;
	 *  s表示所要调整的范围的开始下标,m表示结束的下标,
	 *  即[s,...,m],总个数为m-s+1,m可以取到 
	 */
	private void HeapAdjust(int[] nums,int s,int m){
		int i,temp;
		temp = nums[s];//先取出当前元素s
		for(i=2*s+1;i<=m;i=i*2+1){//从s结点的左子结点开始,也就是2s+1处开始,沿关键字较大的孩子结点向下筛选
			if(i<m && nums[i]<nums[i+1]){//i为孩子节点中关键字较大的记录的下标;i<m保证右孩子存在
				i++;
			}
			if(temp<nums[i]){
				//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
				nums[s]=nums[i];
				s=i;
			}else
				break;		
		}
		nums[s]=temp;//将当前元素插入到最终的位置
	}
	//堆排序
	public void HeapSort(int[] nums,int n){
		int i;
		//1、构建大顶堆
		for(i=n/2-1;i>=0;i--){
			//从第一个非叶结点从下至上,从右至左调整结构
			HeapAdjust(nums,i,n-1);//长度为n,则最后一个元素下标为n-1
		}	
		//2.调整堆结构+交换堆顶元素与末尾元素
		for(i=n-1;i>=0;i--){
			swap(nums,0,i);//将堆顶元素与末尾元素进行交换
			HeapAdjust(nums,0,i-1);//重新对堆进行调整
		}
	}
	
	//归并排序
	public void MergeSort(int[] nums,int n){
		int[] temp = new int[n];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
		MSort(nums,temp,0,n-1);
	}
	private void MSort(int[] nums,int[] temp,int left,int right){
		int mid;
		//if(left==right) temp[left]=nums[right];
		if(left<right){
			mid = (left+right)/2;
			MSort(nums,temp,left,mid);//左边归并排序,使得左子序列有序
			MSort(nums,temp,mid+1,right);//右边归并排序,使得右子序列有序
			Merge(nums,temp,left,mid,right);//将两个有序子数组合并操作
		}
	}
	//right为序列最后一位元素下标
	private void Merge(int[] nums,int[] temp,int left,int mid,int right){
		int i=left;  //左序列指针
		int j=mid+1;  //右序列指针
		int k=0;  //临时数组指针
		while(i<=mid && j<=right){
			if(nums[i]<nums[j]){ 
				temp[k++]=nums[i++];
			}else{
				temp[k++]=nums[j++];				
			}
		}
		while(i<=mid){ //将左边剩余元素填充进temp中
			temp[k++]=nums[i++];
		}
		while(j<=right){  //将右序列剩余元素填充进temp中
			temp[k++]=nums[j++];
		}
		k = 0;
		while(left<=right){  //将temp中的元素全部拷贝到原数组中
			nums[left++]=temp[k++];
		}
	}
	//快速排序
	public void QuickSort(int[] nums,int n){
		QSort(nums,0,n-1);
	}
	
	public void QSort(int[] nums,int low,int high){
		int pivot;
		if(low<high){
			pivot=Partition(nums,low,high);/*将L->r[low..high]一分为二,*/
			/*算出枢轴值pivot */
			QSort(nums,low,pivot-1);
			QSort(nums,pivot+1,high);
		}
	}
	public int Partition(int[] nums,int low,int high){
		int pivotkey=nums[low];
		while(low<high){
			while(low<high && nums[high]>=pivotkey){
				high--;
			}
			swap(nums,low,high);
			while(low<high && nums[low]<=pivotkey){
				low++;
			}
			swap(nums,low,high);
		}
		return low;
	}
	//二叉排序树
	class Node{//二叉排序树的结点类
		public int data;
		public Node left;
		public Node right;
		public Node(int data){
			this.data = data;
			this.left = null;
			this.right = null;
		}
	}
	private Node root=null;
	static int ii =0;//指针,将递归中序遍历的有序树放入nums数组中
	public void BSTSort(int[] nums,int n){
		CreateBST(nums,n);//根据待排序数组生成二叉排序树	
		MidOrderTraverse(root,nums);
	}
	public void InsertNode(int data){
		Node newNode = new Node(data);
		if(root == null){
			root = newNode;
		}else{
			Node current = root;
			Node parent = current;
			while(current != null){
				parent = current;
				if(data < current.data){
					current = current.left;
				}else{
					current = current.right;
				}
			}
			if(data < parent.data){
				parent.left = newNode;
			}else{
				parent.right = newNode;
			}
		}
	}	
	public void CreateBST(int[] nums,int n){
		for(int i = 0;i<n;i++){
			InsertNode(nums[i]);
		}
	}
	//二叉树中序遍历
	public void MidOrderTraverse(Node root,int[] nums){
		if(root != null){
			MidOrderTraverse(root.left,nums);
			nums[ii++]=root.data;
			MidOrderTraverse(root.right,nums);
		}	
	}

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Sort ss = new Sort();
		ss.BSTSort(ss.nums, ss.nums.length);
		for(int i = 0;i<ss.nums.length;i++)
			System.out.println(ss.nums[i]);	
	}
}

猜你喜欢

转载自blog.csdn.net/ncut_nwpu/article/details/79994288