归并排序实现(Java)

归并排序法(Merge Sort,以下简称MS)是分治法思想运用的一个典范。其主要算法操作可以分为以下步骤:
Step 1:将n个元素分成两个含n/2元素的子序列
Step 2:用MS将两个子序列递归排序(最后可以将整个原序列分解成n个子序列)
Step 3:合并两个已排序好的序列
易知,MS的关键在于Merge过程。对于这一过程的理解,算法导论中给出了一个形象的模型。
即假设桌面上有两堆已排序好的的牌,且每一堆都正面朝下放置。然后我们分别从两堆牌中选取顶上的一张牌(选取之后,堆顶端又会露出新的顶牌),选取较小的一张,放入输出堆,另一张放回。
重复这一步骤,最后直到一堆牌为空。由于两堆牌都是已排序,所以可知,只要将剩下的那堆牌盖到输出堆即完成整个排序过程。

    public int[] mergeSort(int[] A, int n) {
        // write code here
        sort(A, 0, n - 1);
        return A;
    }

    public void sort(int[] data, int left, int right) {
        if (left < right) {
            int middle = (left + right) / 2;
            // 划分左右
            sort(data, left, middle);
            sort(data, middle + 1, right);
            // 合并左右
            merge(data, left, middle, right);
        }
    }

    // 合并左右两个子数组
    public void merge(int[] data, int left, int middle, int right) {
        // 临时数组
        int[] tempArr = new int[right - left + 1];
        // 左边数组游标
        int leftIndex = left;
        // 右边数据游标
        int rightIndex = middle + 1;
        // 临时数组游标
        int tempIndex = 0;

        while (leftIndex <= middle && rightIndex <= right) {
            // 临时数组选取左、右子数组中小数值
            if (data[leftIndex] < data[rightIndex]) {
                tempArr[tempIndex++] = data[leftIndex++];
            } else {
                tempArr[tempIndex++] = data[rightIndex++];
            }
        }
        // 剩余的直接放入
        while (leftIndex <= middle) {
            tempArr[tempIndex++] = data[leftIndex++];
        }
        // 剩余的直接放入
        while (rightIndex <= right) {
            tempArr[tempIndex++] = data[rightIndex++];
        }
        // 将临时数组放回原数组相应位置
        int temp = 0;
        while ((temp + left) <= right) {
            data[left + temp] = tempArr[temp];
            temp++;
        }
    }

归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的

数据结构与算法的外部排序是一种处理大量数据(通常大于内存容量)的有效方法,其中归并排序是一个常见的策略。归并排序是一种分治法,它将大文件分割成小块,分别在内存中排序,然后合并这些已排序的部分。 以下是使用Java实现外部归并排序的一个简化版本: ```java import java.io.*; class ExternalMergeSort { private static final int BUFFER_SIZE = 1024; // 内存缓冲区大小 void mergeSort(File file, File tempFile) throws IOException { if (file.length() <= BUFFER_SIZE) return; // 如果文件小,则直接读入内存排序 RandomAccessFile rafIn = new RandomAccessFile(file, "r"); RandomAccessFile rafTemp = new RandomAccessFile(tempFile, "rw"); long length = rafIn.length(); long blockSize = Math.min(length, BUFFER_SIZE); int[] buffer = new int[(int) blockSize]; for (long start = 0; start < length; start += blockSize) { rafIn.seek(start); rafIn.read(buffer); // 读取一块数据到内存 merge(buffer, rafTemp, start, blockSize); } rafTemp.close(); // 关闭临时文件 mergeSort(tempFile, file); // 对剩余部分递归排序 rafIn.close(); } private void merge(int[] buffer, RandomAccessFile rafTemp, long start, int blockLength) throws IOException { int i = 0, j = 0, k = start; while (i < blockLength && j < blockLength) { if (buffer[i] <= buffer[j]) { rafTemp.writeInt(buffer[i++]); } else { rafTemp.writeInt(buffer[j++]); } } // 把未复制完的数据追加到临时文件 while (i < blockLength) { rafTemp.writeInt(buffer[i++]); } } } // 使用示例 public static void main(String[] args) { try { ExternalMergeSort sort = new ExternalMergeSort(); File largeFile = new File("large.txt"); // 待排序的大文件 File tempFile = new File("temp.txt"); // 临时存储文件 sort.mergeSort(largeFile, tempFile); } catch (IOException e) { e.printStackTrace(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值