java 排序算法 折半 堆 希尔 快速 整理

Posted 小夥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 排序算法 折半 堆 希尔 快速 整理相关的知识,希望对你有一定的参考价值。

试题1:折半查找
折半查找是在有序表中,把待查找数据值与查找范围的中间元素值进行比较,会有三种情况出现:
       1)待查找数据值与中间元素值正好相等,则放回中间元素值的索引。
       2)待查找数据值比中间元素值小,则以整个查找范围的前半部分作为新的查找范围,执行1),直到找到相等的值。
       3)待查找数据值比中间元素值大,则以整个查找范围的后半部分作为新的查找范围,执行1),直到找到相等的值
       4)如果最后找不到相等的值,则返回不存储数据的备用单位0。
      给你的问题是,标准输入一升序排列有序整数表,使用折半查找方法查找一个给定的整数值,查找中是通过使用表中的元素与给定的元素值进行比较完成查找,需要你依次输出在折半查找过程中使用过比较的元素值。
  输入:标准输入,输入的第一行为一个正整数n,表示需要查找表的元素个数;第二行为具有升序序列的n个整数,两数之间为一个空格隔开;第三行为需要你查找的整数。
  输出:标准输出,第一行依次输出在查找过程中进行比较的元素值,两数之间使用一个空格隔开。输出的第二行输出查找结果,如果查找元素在表中,输出该元素的序号(从1开始编号),如果查找元素不在表中,输出“NO"。
  输入样例:
  13
  7 14 18 21 23 29 31 35 38 42 46 49 52
  21
  输出样例:
  31 18 23 21
  4

思路:用递归,实现起来比较简单。

import java.util.*;
public class Main {

	public static void main(String[] args) {
		int n, m;
		int[] s;
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		s = new int[n+1];
		for(int i = 1; i <= n; i++)
			s[i] = in.nextInt();
		m = in.nextInt();
		find(1, n, m, s);
		in.close();
	}

	public static void find(int s, int e, int m, int[] st){
		int index = (s + e) / 2;
		if(st[index] < m){
			System.out.printf(st[index] + " ");
			find(index+1, e, m, st);
		}else if(st[index] > m){
			System.out.printf(st[index] + " ");
			find(s, index-1, m, st);
		}else 
			System.out.printf("%d\n%d\n", st[index], index);
	}
}

试题2:堆排序
堆排序的思想实际上利用完全二叉树存储在数组中,通过调整完全二叉树成为大顶堆获得一个排序表的最大值进行排序的方法,大顶堆满足根节点比子树旳节点大。堆排序主要是通过大顶堆旳根元素与未完成排序旳最后一个元素进行交换,将交换后旳完全二叉树不满足大顶堆要求调整到满足满足要求,调整通过如下方法完成:
       void heapAdjust(int[] R,int s,int t);其中,数组R中存储旳二叉树,只有以R[s]为根子树,其左右子树之间可能不满足大顶堆特征。
      调整堆旳操作难点为根子树节点编号为i,则左子树节点编号为2*i,右子树节点编号为2*i+1;通过比较子树旳大小选择大旳子树进行调整,一直调整到根节点比子节点大,再将根节点旳值插入到最后调整旳节点。要完成堆排序,在调整旳基础上可以通过从堆底往堆顶进行调整获得初始堆,然后通过N-1次调整完成排序,控制流程为:
            void heapSort(int[] R){
             int i;
             int N=R.length-1;
             for(i=N/2;i>0;i--){
                  heapAdjust(R,i,N);
             }
             for(i=N;i>1;i--){
                  R[0]=R[1];R[1]=R[i];R[i]=R[0];
                      heapAdjust(R,1,i-1);
                 }
            }
          给你旳问题是,将标准输入的n个整数采用堆排序,并需要显示建成旳初始堆,并完成该数据的排序。
输入:标准输入,输入的第一行为整数的个数n值,第二行为n个整数,每个整数之间为一个空格。
输出:标准输出,第一行依次输出排序过程中建成旳初始堆在数组中的存储值,每个输出数据之间使用一个空格隔开,第二行输出排序后的序列,每个输出数据之间使用一个空格隔开。
输入样例:
14
39 80 76 41 13 29 50 78 30 11 100 7 41 86
输出样例:
100 80 86 78 39 41 76 41 30 11 13 7 29 50 
7 11 13 29 30 39 41 41 50 76 78 80 86 100

import java.util.Scanner;

public class Main {   

	public static void main(String args[]) {   
		Scanner in=new Scanner(System.in);
		int n = in.nextInt();
		int[] array = new int[n + 1];
		
		for(int i = 1; i <= n; i++)
			array[i] = in.nextInt();
		
		adjust(array);
		print(array);
		heapSort(array);
		print(array);
		in.close();
	}  
	
	//输出
	public static void print(int[] list) { 
		System.out.print(list[1]);
		for (int i = 2; i < list.length; i++) {   
			System.out.print(" " + list[i]);   
		}   
		System.out.println();
	}   

	//交换
	public static void swap(int[] heap, int a, int b) {
		int temp = heap[a];
		heap[a] = heap[b];
		heap[b] = temp;
	}   
 
	//根据定义,树节点前一半是有孩子的,所以,从这里开始调整
	public static void adjust(int[] heap){
		for (int i = heap.length / 2; i > 0; i--) 
			adjust(heap, i, heap.length - 1); 
	}  

	public static void adjust(int[] heap,int i, int n) {
		int child;
		while (i <= n / 2) {
			child = i * 2;
			if(child + 1 <= n && heap[child] < heap[child + 1])
				child += 1;//使child指向值较大的孩子
			if(heap[i] < heap[child]){
				swap(heap, i, child);
				//交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整
				i = child;
			}  else break;
		}
	}

	//对一个最大堆heap排序  
	public static void heapSort(int[] heap) {    
		for (int i = heap.length - 1; i > 0; i--) {    
			//把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可 
			swap(heap,1, i);
			adjust(heap,1, i - 1);
		}    
	}    
}   



试题3:快速排序
        快速排序的核心操作是划分,通过某个数据将原来排序表分成两部分,前面部分比该数小,后面数据比该数据大或相等,该数据就为排序后的位置,即该数据完成排序。如果定义一个排序表的划分方法为:      int partition(int[] R,int low,int high);     其中,low,high表示将数据R的第low个数据到high个数据进行划分,返回到整数为划分后到支点记录位置;     定义完成划分方法后,通过如下调用完成快速排序:     void QuickSort(int[] R,int s,int t){           if(s<t){              i=partition(R,s,t);              QuickSort(R,s,i-1);               QuickSort(R,i+1,t);          }     }     建议每次划分选择第一个元素为支点记录进行编程。给你到问题是,将标准输入的n个整数采用快速排序,并需要显示出每次划分所使用到分支点记录,并完成该数据的排序。输入:标准输入,输入的第一行为整数的个数n值,第二行为n个整数,每个整数之间为一个空格。输出:标准输出,输出的第一行依次输出排序过程中使用的支点记录,每个输出数据之间使用一个空格隔开,第二行输出排序后的序列,每个输出数据之间使用一个空格隔开。输入样例:1439 80 76 41 13 29 50 78 30 11 100 7 41 86输出样例:39 7 11 30 13 50 41 76 100 86 78 7 11 13 29 30 39 41 41 50 76 78 80 86 100

import java.util.*;

public class Main {
	//用于保存使用的支点记录
	private static List<Integer> ans;
	
	public static void main(String[] args) {
		ans = new ArrayList<Integer>();
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] a = new int[n + 1];
		for(int i = 1; i <= n; i++){
			a[i] = in.nextInt();
		}
		QuickSort(a, 1, n);
		//输出使用的支点记录
		print_ans();
		//输出排序后的值
		print(a);
		in.close();
	}

	public static void QuickSort(int[] R, int s, int t){
		if(s < t){
			int i = partition(R, s, t);
			ans.add(R[i]);
			QuickSort(R, s, i-1);
			QuickSort(R, i+1, t);          
		}
	}

	public static int partition(int[] R, int s, int t){
		int i = s, j = t;
		int x = R[s];
		while(i < j){
			//从右向左找小于x的数来填R[i]  
			while(i < j && R[j] >= x)
				j--;
			if(i < j){
				R[i] = R[j];
				i++;
			}
			//从左向右找大于或等于x的数来填R[j]
			while(i < j && R[i] < x)
				i++;
			if(i < j){
				R[j] = R[i];
				j--;
			}
		}
		R[i] = x;
		return i;
	}

	public static void print(int[] R){
		System.out.print(R[1]);
		for(int i = 2; i < R.length; i++){
			System.out.print(" " + R[i]);
		}
		System.out.println();
	}
	
	public static void print_ans(){
		if(!ans.isEmpty()){
			System.out.print(ans.get(0));
			for(int i = 1; i < ans.size(); i++){
				System.out.print(" " + ans.get(i));
			}
			System.out.println();
		}
	}
	
}


试题4:希尔排序

希尔排序的思想是:先选择一个小于排序数据个数n的整数di(称为步长,一般为小于n的质数),将间隔di的数为一组,对每组的元素进行直接插入排序,即将需要排序的数据插入到已经排序好拢到序列中。当步长为1时,完成整个数据的排序。排序的流程为:
    1、根据步长的个数,对于每个步长进行分组;
    2、对每组进行插入排序,主要操作如下:
          1)如果未有存在未有序的数据,将该数据存储到临时遍历R[0]中;
          2)将前面比他大的数据全部向后移动一位;
          3)再将R[0]的数据插入到最后移动到数据位置;
  给你到问题是,将标准输入的n个整数采用希尔排序,步长取5,3,1,并需要显示出每次需要插入的数,并完成该数据的排序。
输入:标准输入,输入的第一行为整数的个数n值,第二行为n个整数,每个整数之       间为一个空格。
输出:标准输出,输出第一行依次输出排序过程中需要插入的数,每个输出数据之间使用一个空格隔开,第二行输出排序后的序列,每个输出数据之间使用一个空格隔开。
输入样例:
14
39 80 76 41 13 29 50 78 30 11 100 7 41 86
输出样例:
29 50 30 11 7 41 39 13 86 7 29 11 30 41 50 80 78 
7 11 13 29 30 39 41 41 50 76 78 80 86 100


import java.util.*;

public class Main {

	//用于保存每次需要插入的数
	private static List<Integer> ans;

	public static void main(String[] args) {
		ans = new ArrayList<Integer>();
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] a = new int[n];
		for(int i = 0; i < n; i++){
			a[i] = in.nextInt();
		}
		shellsort(a);
		//输出每次需要插入的数
		print_ans();
		//输出排序后的结果
		print(a);
		in.close();
	}

	public static void shellsort(int[] data) {  
		int j = 0;  
		int temp = 0;  
		for (int increment = 5; increment > 0; increment -= 2) {  
			for (int i = increment; i < data.length; i++) {  
				temp = data[i];  
				boolean flag = true;
				for (j = i; j >= increment; j -= increment) {  
					if(temp < data[j - increment]){  
						data[j] = data[j - increment];         	
						if(flag) {
							ans.add(temp);
							flag = false;
						}
					}else break;  
				}
				data[j] = temp;
			}  
		}  
	} 
	
	public static void print(int[] R){
		System.out.print(R[0]);
		for(int i = 1; i < R.length; i++){
			System.out.print(" " + R[i]);
		}
		System.out.println();
	}

	public static void print_ans(){
		if(!ans.isEmpty()){
			System.out.print(ans.get(0));
			for(int i = 1; i < ans.size(); i++){
				System.out.print(" " + ans.get(i));
			}
			System.out.println();
		}
	}
}



以上是关于java 排序算法 折半 堆 希尔 快速 整理的主要内容,如果未能解决你的问题,请参考以下文章

常见排序算法的实现(归并排序快速排序堆排序选择排序插入排序希尔排序)

排序算法整理:冒泡排序堆排序插入排序归并操作快速排序希尔排序选择排序

java常用排序算法

数据结构学习笔记(八大排序算法)整理与总结

数据结构学习笔记(八大排序算法)整理与总结

插入排序(直接插入排序折半插入排序希尔排序的算法思想及代码实现)