各种排序算法(4)

package nuaa.ds;

public class Sort<T>{
	//插入排序
	public void insertionSort(T[] t,Comparator<T> c){
		for(int i=1;i<t.length;i++){//确定有序序列
			T temp = t[i];//空出位置
			for(int j=i-1;j>=0;j--){//往前依次查找
				if(c.compare(temp, t[j])<0){
					t[j+1] = t[j];//前面的值大就往后移一位
				}else{
					t[j+1] = temp;//前面的值等于或者小于就插入
					break;
				}
				if(j==0){//循环到头了
					t[0] = temp;
				}
				
			}
		}
	}
	
	//希尔排序:思路类似插入排序
	public void shellSort(T[] t,Comparator<T> c){
		//除以2.2分割貌似是最佳的,最后分割必须为1
		for(int gap=t.length/2;gap>0;gap=(gap==2? 1:(int)(gap/2.2))){//加了个分割循环
			for(int i=gap;i<t.length;i+=gap){
				T temp = t[i];//当前的为坑
				for(int j=i-gap;j>=0;j-=gap){//0到i每个都比较,大的往后坑里填,小的就填值
					if(c.compare(t[j], temp)>0){
						t[j+gap]=t[j];
					}else{
						t[j+gap]=temp;
						break;
					}
					if(j==0){//循环到头了
						t[0] = temp;
					}
				}
			}
		}
	}
	
	//冒泡排序
	public void bubbleSort(T[] t,Comparator<T> c){
		for(int i=0;i<t.length;i++){//有length-1个元素要移动
			for(int j=0;j<t.length-i-1;j++){//从开始位置往后扫描
				if(c.compare(t[j], t[j+1])>0){//如果发现前面元素比后面大
					T temp=t[j];t[j]=t[j+1];t[j+1]=temp;//就互换
				}
			}
		}
	}
	
	//选择排序
	public void selectionSort(T[] t,Comparator<T> c){
		for(int i=0;i<t.length;i++){//确定位置当成最小值存放点
			int k=i;
			for(int j=i+1;j<t.length;j++){//从开始位置往后扫描
				if(c.compare(t[k], t[j])>0){//发现小值就记录下标
					k = j;
				}
			}
			T temp=t[i];t[i]=t[k];t[k]=temp;//存放入最小值
		}
	}
	
	//归并排序
	public void mergeSort(T[] t,Comparator<T> c){
		mergeSort(t,0,t.length-1,c);
	}
	
	private void mergeSort(T[] t,int low,int high,Comparator<T> c){
		if(low<high){//分割到一为止,
			int middle = (low+high)/2;
			mergeSort(t,low,middle,c);
			mergeSort(t,middle+1,high,c);
			//单个元素不需要排序,因此排序过程也在if语句里面
			T[] temp = (T[])new Object[high-low+1];
			int a = 0;//temp 的下标
			int lowIndex = low;//low到middle的索引,
			int highStart = middle+1;
			
			while((lowIndex<=middle)&&(high>=highStart)){//排序好的分割2列都有值
				
				if(c.compare(t[lowIndex], t[highStart])<=0){
					temp[a++] = t[lowIndex];
					lowIndex++;
				}else{
					temp[a++] = t[highStart];
					highStart++;
				}
			}
			while(lowIndex<=middle){//索引低的部分还有剩余项
				temp[a++] = t[lowIndex];
				lowIndex++;
			}
			while(high>=highStart){//索引高的部分还有剩余项
				temp[a++] = t[highStart];
				highStart++;
			}
			//重置temp的索引并拷贝回原数组
			for(a=0;a<temp.length;a++){
				t[low++] = temp[a];
				
			}
			
			
		}
		
		
	}
	//快速排序
	public void quickSort(T[] t,Comparator<T> c){
		quickSort(t,0,t.length-1,c);
	}
	
	private void quickSort(T[] t,int low,int high,Comparator<T> c){
		/*if(high-low==1){//分割到2个数快速排序有问题
			this.bubbleSort(t, c);
			return;
			if(c.compare(t[low], t[high])>0){
				T temp=t[low];t[low]=t[high];t[high]=temp;
			}
			
			return;
			
		}*/
		if(low<high){//一个数则不用排序
			int middle = (low+high)/2;
			T temp;//交换值的临时变量
			//三个if确定分割点并将分割点放在最后
			if(c.compare(t[low], t[middle])>0){
				temp = t[low];t[low] = t[middle];t[middle] = temp; 
			}
			if(c.compare(t[low], t[high])>0){
				temp = t[low];t[low] = t[high];t[high] = temp;
			}
			if(c.compare(t[middle], t[high])<0){
				temp = t[middle];t[middle] = t[high];t[high] = temp;
			}
			int lowIndex = low;
			int highIndex = high;
			/**
			 * 循环内只能放小于大于不能放等于,这样2个下标移动的时候才肯定会
			 * 在最小和最大处停下来,而带来的副产品是下标的自增自减一定要放
			 * 在循环内,不然会造成循环。
			 */
			while(true){//等也要停下来防止越界
				while(c.compare(t[++lowIndex], t[high])<0)//lowIndex先开始因此
													//循环break后互换用lowIndex
					;
				while(c.compare(t[--highIndex], t[high])>0)//自增自减放下面是死循环
					;                                      //加等号相等依然执行会越界
				if(lowIndex>=highIndex)
					break;
				temp=t[lowIndex];t[lowIndex]=t[highIndex];t[highIndex]=temp;
			}
			temp=t[lowIndex];t[lowIndex]=t[high];t[high]=temp;
			
			
			quickSort(t,low,lowIndex-1,c);
		
			quickSort(t,lowIndex+1,high,c);
		}
		
	}
	
	//堆排序
	
	public void heapSort(T[] t,Comparator<T> c){
		createHeap(t,t.length-1,c);//建立初堆
		for(int i=t.length-1;i>0;i--){     //每次最后和第一个元素互换,将最大元素
			T temp=t[i];t[i]=t[0];t[0]=temp; //沉底,第一个不需要所以for条件为>0
			reconstruct(t,0,i-1,c); //数组从0~i-1重新构造堆
		}
	}
	
	/**
	 * 数组下标从0开始,二叉树从1开始,注意转换
	 * @param t
	 * @param lastIndex 数组的最后一个索引下标
	 * @param c
	 */
	private void createHeap(T[] t,int lastIndex,Comparator<T> c){
		for(int i=(lastIndex+1)/2;i>=1;i--)//i的值为二叉树的根下标,依次调整为堆
			reconstruct(t,i-1,t.length-1,c);//传递的为数组下标
	}
	/**
	 * 
	 * @param t
	 * @param firstIndex  数组第一个下标
	 * @param lastIndex   数组最后一个下标
	 * @param c
	 */
	private void reconstruct(T[] t,int firstIndex,int lastIndex,Comparator<T> c){
		int first = firstIndex+1;//转化为二叉树
		int last = lastIndex+1;//	      的下标
		int index = first*2;
		while(index<=last){//左子树存在
			if(index+1<=last&&c.compare(t[index], t[index-1])>0){//右子树存在且大
				if(c.compare(t[first-1],t[index])<0){//右子树大于根
					T temp=t[first-1];t[first-1]=t[index];t[index]=temp;
					first = index+1;
					index = 2*first;
				}else{
					break;
				}
			}else if(c.compare(t[first-1], t[index-1])<0){
				T temp=t[first-1];t[first-1]=t[index-1];t[index-1]=temp;
				first = index;
				index = first*2;
			}else{
				break;
			}
		}
	}
	
}

一些盲点:归并排序究竟在外部排序怎么用?外部排序哪些算法?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值