`

Java中的Arrays.sort 分析及其非递归实现——Bash

 
阅读更多

上篇文章我们讨论了快速排序算法,它与归并算法同属分治算法的一种。

两者在实现上很相似,都使用了分治递归的策略来实现。

 

相信大家对快排和归并排序都不陌生,不过我们平常接触到的一般是这两种算法的递归实现方式。

以Java为例,其Arrays类中的sort在排序Object的时候用的就是归并排序。

不过其在实现上做了优化,在子问题足够小时(每个递归子序列长度不大于7)通过插入排序完成这个子序列的排序。

 

概括而言,Java中的Arrays.sort在排序Object对象的数组时用的是归并排序+插入排序的方式,即对插入排序结果的归并。

 

Java中的实现如下:

 

 

private static final int INSERTIONSORT_THRESHOLD = 7;

    /**
     * Src is the source array that starts at index 0
     * Dest is the (possibly larger) array destination with a possible offset
     * low is the index in dest to start sorting
     * high is the end index in dest to end sorting
     * off is the offset to generate corresponding low, high in src
     */
    private static void mergeSort(Object[] src,
				  Object[] dest,
				  int low,
				  int high,
				  int off) {
	int length = high - low;

	// Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
			 ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

 

上述方式通过函数递归调用实现,本文接下来要讨论的是该方案的非递归实现,实现语言是Bash。

与上篇文章中使用的方法类似,通过栈的数据结构特点,模拟函数的递归调用。

 

由于快排的递归操作不需要对子问题进行合并,因此只需要将问题按照一定策略分解,并将子问题解决。

而归并排序则需要将子问题的结果做进一步的处理,因此,在栈空间的使用上,不仅需要跟踪递归调用的栈,还需要记录子问题计算结果的栈,用来对子问题结果做递归合并处理。

 

这种方式有点像通过逆波兰式计算表达式结果的思路,具体代码如下:

 

 

#!/bin/bash


declare -a inputArray=(1 3 2 4 5 9 8 7 0);

##init for large number test
for i in `seq 1000`
do
    inputArray[$i]=$RANDOM;
done
inputLength=${#inputArray[@]};
lastIndex=$((inputLength-1));

## trace Stack for recursive calls
declare -a traceStackStart;
declare -a traceStackEnd;
traceStackDeep=0;

##stack for the already sorted sub Array to merge
declare -a mergeStackStart;
declare -a mergeStackEnd;
mergeStackDeep=0;

## begin recursive call...
traceStackStart[0]=0;
traceStackEnd[0]=$lastIndex;
traceStackDeep=1;

## recursive call until traceStack empty
while [ $traceStackDeep -ne 0 ]
do
    #pop stack
    traceStackDeep=$((traceStackDeep-1));
    low=${traceStackStart[$traceStackDeep]};
    hig=${traceStackEnd[$traceStackDeep]};
    if [ "$low" = "+" ]; then
        mergeStackDeep=$((mergeStackDeep-1));
        l1=${mergeStackStart[$mergeStackDeep]};
        h1=${mergeStackEnd[$mergeStackDeep]};
        mergeStackDeep=$((mergeStackDeep-1));
        l2=${mergeStackStart[$mergeStackDeep]};
        h2=${mergeStackEnd[$mergeStackDeep]};

        ## merge sorted subArray here
        i=0;
        j=0;
        desLow=0;
        declare -a tmp=(0);
        for((i=l1,j=l2;i<=h1 && j<=h2;desLow++))
        do
            if [ ${inputArray[$i]} -le ${inputArray[$j]} ]; then
                tmp[$desLow]=${inputArray[$i]};
                i=$((i+1));
            else
                tmp[$desLow]=${inputArray[$j]};
                j=$((j+1));
            fi
        done

        if [ $i -gt $h1 ]; then
            for((;j<=h2;j++,desLow++))
            do
                tmp[$desLow]=${inputArray[$j]};
            done
        else
            for((;i<=h1;i++,desLow++))
            do
                tmp[$desLow]=${inputArray[$i]};
            done
        fi

        for((tmpI=0,i=l1;i<=h2;i++,tmpI++))
        do
            inputArray[$i]=${tmp[$tmpI]};
        done

        ## push the merge sort result to the mergeStack
        mergeStackStart[$mergeStackDeep]=$l1;
        mergeStackEnd[$mergeStackDeep]=$h2;
        mergeStackDeep=$((mergeStackDeep+1));
    elif [ $low -lt $hig ]; then
        l=$low;
        h=$hig;
        space=$((h-l));
        if [ $space -le 7 ]; then
            #insertion sort here
            for((i=l+1;i<=h;i++))
            do
                for((j=i;j>l;j--))
                do
                    if [ ${inputArray[$j-1]} -gt ${inputArray[$j]} ]; then
                        tmp=${inputArray[$j-1]};
                        inputArray[$j-1]=${inputArray[$j]};
                        inputArray[$j]=$tmp;
                    fi
                done
            done
            mergeStackStart[$mergeStackDeep]=$l;
            mergeStackEnd[$mergeStackDeep]=$h;
            mergeStackDeep=$((mergeStackDeep+1));
        else
            m=$((l+(h-l)/2));
            n=$((m+1));
            traceStackStart[$traceStackDeep]="+";
            traceStackEnd[$traceStackDeep]="+";
            traceStackDeep=$((traceStackDeep+1));
            traceStackStart[$traceStackDeep]=$l;
            traceStackEnd[$traceStackDeep]=$m;
            traceStackDeep=$((traceStackDeep+1));
            traceStackStart[$traceStackDeep]=$n;
            traceStackEnd[$traceStackDeep]=$h;
            traceStackDeep=$((traceStackDeep+1));
        fi
    fi
done

echo ${inputArray[*]};

 

 

 

 

 

1
0
分享到:
评论

相关推荐

    JAVA基于Arrays.sort()实现数组升序和降序

    在 Java 中,排序数组是非常常见的操作之一,而 Java 提供了多种方式来实现数组的排序,其中一种常用的方法是使用 Arrays.sort() 方法。今天,我们将详细介绍如何使用 Arrays.sort() 方法来实现数组的升序和降序排序...

    Java Arrays.sort和Collections.sort排序实现原理解析

    Java中的`Arrays.sort()`和`Collections.sort()`是两个常用的排序函数,它们分别用于对数组和集合进行排序。这两个函数在内部实现上有所不同,但都基于高效的排序算法。 首先,`Collections.sort()`方法在处理列表...

    深入理解java中Arrays.sort()的用法

    "深入理解Java中Arrays.sort()的用法" 在Java中,Arrays.sort()是一个非常重要的方法,它可以对数组进行排序。该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。但是sort()的参数有好几种,基本上...

    java中的arrays.sort()代码详解

    "Java中的Arrays.sort()代码详解" Arrays.sort()是Java中的一种排序算法,该方法可以对数组进行排序,具体来说,它可以对基本类型数组和对象数组进行排序。在本文中,我们将详细介绍Arrays.sort()的使用方法,包括...

    System.arraycopy和Arrays.copyOf

    `System.arraycopy` 和 `Arrays.copyOf` 都是Java中用于复制数组的方法,但它们在使用和处理异常情况上有所不同。这两个方法在处理数组复制时,提供了便利和效率,但各有其适用场景。 `System.arraycopy` 是一个...

    Java中Arrays.asList()方法详解及实例

    Java中Arrays.asList()方法详解及实例 Arrays.asList()方法是Java中一个常用的方法,它将数组转换为列表。该方法的签名为`public static &lt;T&gt; List&lt;T&gt; asList(T... a)`,它可以接受变长参数,通常情况下是一个数组...

    java arrays类.docx

    Arrays.sort(array); System.out.println(Arrays.toString(array)); // 搜索元素 int index = Arrays.binarySearch(array, 3); System.out.println("元素 3 的索引:" + index); // 复制数组 int[] ...

    Java Arrays.asList使用方法解析

    "Java Arrays.asList使用方法解析" ...Java Arrays.asList使用方法解析是一个非常重要的知识点,需要我们牢记Arrays.asList方法返回的ArrayList对象的行为与我们通常使用的List集合不同,以避免在编程中出现错误。

    Java用Arrays.asList初始化ArrayList实例方法

    Java中使用Arrays.asList初始化ArrayList实例方法 在 Java 中,使用 Arrays.asList 方法可以快速创建一个 List 集合,但是需要注意的是,这个方法返回的 ArrayList 并不是 java.util.ArrayList 对象,而是一个内部...

    你清楚Arrays.binarySearch()方法的返回值吗?

    `Arrays.binarySearch()`方法允许我们在有序数组中查找指定元素,并返回该元素的索引。如果数组中不存在该元素,则会返回一个负数,这个负数的绝对值是插入该元素位置的前一个位置。 首先,让我们详细了解一下`...

    android多语言strings.xml,arrays.xml转xls与xls转xml脚本程序

    `strings.xml`和`arrays.xml`文件是Android资源文件中的核心组件,用于存储应用程序中的文本和数组数据。这些文件通常包含不同语言的字符串资源,以便在不同地区展示相应的本地化内容。 本话题涉及一个脚本程序,它...

    java的Arrays类的应用.doc

    - `Arrays.binarySearch()`方法实现了二分查找算法,用于在已经排序的数组中查找特定元素。如果找到,返回元素的索引;否则,返回一个负数,该负数的绝对值表示插入元素的位置。例如,`Arrays.binarySearch(array1,...

    Java中Arrays类详解.docx

    - 如果只想对数组的一部分进行排序,可以传递额外的参数,如`Arrays.sort(array, fromIndex, toIndex)`,其中`fromIndex`和`toIndex`分别表示排序的起始和结束位置(包含起始,不包含结束)。 3. **数组复制**: ...

    Arrays.asList方法总结

    `Arrays.asList`方法是Java中一个非常实用的工具,它允许我们将数组转换为`List`对象,以便在处理数组时可以利用`List`接口提供的便利。然而,这个方法有一些特殊的特性和限制,需要我们理解清楚才能正确使用。下面...

    Java5.0数组排序

    虽然Java 5.0的`Arrays.sort()`方法不能直接用于多维数组,但可以通过递归或循环的方式,对二维数组的每一行进行单独排序。 四、`Collections.sort()`与`List` 除了`Arrays.sort()`,Java 5.0的`Collections.sort...

    Apress.PHP.Arrays.Single.Multi-dimensional.Associative.and.Object.Arrays.

    Apress.PHP.Arrays.Single.Multi-dimensional.Associative.and.Object.Arrays.in.PHP.7.1484225554.rar 最新书籍,精讲PHP数组,文字版PDF

    Java.SE.7.Programming.Essentials

    Using Java Arrays Chapter 5. Using Loops in Java Code Chapter 6. Encapsulating Data and Exposing Methods in Java Chapter 7. Using Java Methods to Communicate Chapter 8. Using Java Constructors ...

    java sort排序算法实例完整代码

    Java中的`sort`排序算法是Java集合框架的重要组成部分,主要用于对List接口的实现类进行排序。这个算法在Java中主要体现在`java.util.Arrays`和`java.util.Collections`两个类中,提供了对数组和集合的排序功能。...

    java performance12

    在此过程中,首先将列表转换为数组,然后调用 `Arrays.sort()` 对数组进行排序,最后再将排序后的数组元素重新放回原列表中。 #### 2. `Arrays.sort()` 的内部实现 `Arrays.sort()` 方法实现了快速排序算法。对于...

    PHP.Arrays.in.PHP.7

    Gain an in-depth understanding of PHP 7 arrays. After a quick overview of PHP 7, each chapter concentrates on single, multi-dimensional, associative, and object arrays. PHP Arrays is a first of its ...

Global site tag (gtag.js) - Google Analytics