排序算法(二)_希尔排序、快速排序、归并排序的Java实现

2024-06-14 02:08

本文主要是介绍排序算法(二)_希尔排序、快速排序、归并排序的Java实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       今天来聊聊Java数据结构中关于排序的问题,如题涉及到的有希尔排序,归并排序,快速排序。

        希尔排序(Shell Sort):希尔排序其实就是一种特殊处理过的插入排序,是按指定的间隔增量进行插入排序,所以希尔排序也叫减小间隔增量插入排序。相对于普通的插入排序而言,希尔排序会对排序的过程加以控制,从而避免了一些极端输入情况(如一个倒序输入数列)对于算法运行时间的影响。

         归并排序(Merge Sort):归并排序是通过分治法思想来实现的。通过不断将问题切割成两个规模更小的子问题,知道基本情况(Base Case),然后将这些子问题的解整合起来合成问题的解。一般情况下归并排序优于希尔排序。

         快速排序(Quick Sort):快速排序也是一种分治思想的体现,快速排序的优点在于他是原址排序的,即不需要额外的空间开销。虽然和归并排序一样,它的算法时间也是theta(nlgn),但是通常情况下快速排序比归并排序快3倍左右。

最后扯一下“随机化的快速排序”,当快速排序的输入数列是已经排好序的,那么快速排序的效率就会变低。即该算法的运行时间受输入数据的影响,在进行排序之前对输入数据进行一次“随机化”处理可以避免算法运行时间受输入的影响。这样算法的运行时间就是“随机化”后的输入数列的一个概率分布问题。 即“随机化”处理后,我们仍然可能得到一个"很差"的输入数列,但是这个"最差"数列出现的概率是很低的。

         MergeSort:

package com.wly.algorithmbase.sort;/*** 归并排序实现* @author wly**/
public class MergeSort {/*** 以pivot为分割点分成[0,pivot)和[pivot,array.length)两部分进行归并* @param array* @param pivot* @return*/public void sort(int[] array,int left,int right) {if(left == right) {return ;}int pivot = (left+right)/2;sort(array, left, pivot);sort(array,pivot+1,right);merge(array, left, pivot, right);}/*** 合并数组方法一* 注意:[low,high]不能分割成[low,mid)和[mid,high]* 因为当low=0,mid=0,high=1时,无法进入循环* 而分割成[low,mid]和(mid,high]的话,就可以进入循环* */public void merge(int[] array,int low,int mid,int high) {int[] tempArray = new int[array.length];for(int i=0;i<tempArray.length;i++) {tempArray[i] = array[i];};int i = low;int j = mid+1;int index = low; //注意这里的是从index开始的while(i <= mid && j <= high) {if(tempArray[i] < tempArray[j]) {array[index++] = tempArray[i];i ++;} else {array[index++] = tempArray[j];j++;}}while(i <= mid) {array[index++] = tempArray[i];i++;}while(j <= high) {array[index++] = tempArray[j];j ++;}}//	/**
//	 * 合并数组方法二
//	 * @param a1
//	 * @param a2
//	 */
//	public int[] merge(int[] a1,int[] a2) {
//		int[] a3 = new int[a1.length + a2.length];
//		int i = 0;
//		int j = 0;
//		while(i < a1.length && j < a2.length) {
//			if(a1[i] < a2[j]) {
//				a3[i+j] = a1[i];
//				i ++;
//			} else {
//				a3[i+j] = a2[j];
//				j++;
//			}
//		}
//		while(i < a1.length) {
//			a3[i+j] = a1[i];
//			i++;
//		}
//		while(j < a2.length) {
//			a3[i+j] = a2[j];
//			j ++;
//		}
//		return a3;
//	}
}

        QuickSort:

package com.wly.algorithmbase.sort;/*** 快速排序实现* @author wly**/
public class QuickSort{public void sort(int[] array,int left,int right) {if(left >= right) {return ;} else {int pivot = partition(array, left,right);sort(array,left, pivot-1); //注意-1操作,因为递归求解范围不包括pivotsort(array,pivot+1,right); //注意+1操作,因为递归求解范围不包括pivot}}/*** 拆分数组成两个部分,并且以pivot为基准,进行划分* @param array*/private int partition(int[] array,int left,int right) {//随机生成分割点int pivot = (int) (Math.random() * (right - left)) + left;int pValue = array[pivot];int leftPos = left;int rightPos = right;while(leftPos != rightPos) {while(array[leftPos] < pValue) {leftPos ++;}while(array[rightPos] > pValue) {rightPos --;}exchange(array,leftPos,rightPos);}return leftPos;}/*** 交换数组中指定的两个元素* @param array* @param x1* @param x2*/public void exchange(int[] array,int x1,int x2) {int temp = array[x1];array[x1] = array[x2];array[x2] = temp;}
}

        ShellSort:

package com.wly.algorithmbase.sort;/*** 希尔排序是基于插入排序的,是一种增量递减的插入排序* 也可以说插入排序是一种增量为1的希尔排序* @author wly*/
public class ShellSort {public void sort(int array[], int interval) {int temp;int n = array.length / interval; // 每一分组包含的元素个数if (n == 1) {return;} else {// 对分组进行插入排序int j = 1;while (j < n) {// 1.保存要排序元素到临时变量temp = array[j * interval];for (int k = 0; k < j; k++) {// 2.寻找插入位置if (temp <= array[k * interval]) {// 3.移动插入位置和欲排序元素之间的元素,以腾出位置for (int m = j; m > k; m--) { // 偶滴神啊,好多i,j,k啊~~~array[m * interval] = array[(m - 1) * interval];}// 4.插入元素array[k * interval] = temp;break;}}j++;}}if (interval > 1) {sort(array, getInterval(interval));}}/*** 递减增量* @param interval 当前增量* @return*/private int getInterval(int interval) {if (interval == 1) {return 0;} else {return (interval / 30) + 1;}}
}

        测试一下:

package com.wly.algorithmbase.sort;public class Test {public static void main(String[] args) {//1.测试快速排序System.out.println("--快速排序--");System.out.print("排序前:");int[] array = {3,5,1,6,2,8,7,4,9};for(int i:array) {System.out.print(i + " ");}System.out.print("\n排序后:");QuickSort quickSort = new QuickSort();quickSort.sort(array, 0, array.length-1);for(int i:array) {System.out.print(i + " ");}//2.测试归并排序System.out.println("\n--归并排序--");System.out.print("排序前:");int[] array2 = {3,6,1,2,8,7,9,5,4};for(int i:array2) {System.out.print(i + " ");}System.out.print("\n排序后:");MergeSort mergeSort = new MergeSort();mergeSort.sort(array2, 0, 8);for(int i:array2) {System.out.print(i + " ");}//3.测试希尔排序System.out.println("\n--希尔排序--");System.out.print("排序前:");int[] array3 = {4,7,2,1,8,9,3,6,5};for(int i:array3) {System.out.print(i + " ");}System.out.print("\n排序后:");ShellSort shellSort = new ShellSort();shellSort.sort(array3, 3);for(int i:array3) {System.out.print(i + " ");}}
}

         运行结果:

--快速排序--
排序前:3 5 1 6 2 8 7 4 9 
排序后:1 2 3 4 5 6 7 8 9 
--归并排序--
排序前:3 6 1 2 8 7 9 5 4 
排序后:1 2 3 4 5 6 7 8 9 
--希尔排序--
排序前:4 7 2 1 8 9 3 6 5 
排序后:1 2 3 4 5 6 7 8 9 

        以上三种排序有个共同点,都是"比较型"的排序算法,按照算法导论公开课中讲到的凡是"比较型"的排序算法其运行时间不可能低于theta(nlgn),视频中给出了证明,这里不再赘述。具体可查看公开课的第五章—线性时间排序。

        O啦~~~

        转载请保留出处:http://blog.csdn.net/u011638883/article/details/13769747

        谢谢!!


这篇关于排序算法(二)_希尔排序、快速排序、归并排序的Java实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059071

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu