通用类型的两路归并算法实现(三)——运用Comparator实现更加通用的两路归并算法

    上篇通用类型的两路归并算法实现(二)——面向接口实现通用类型的两路归并,我们通过Comparable接口实现了对任意实现了Comparable接口的类型对象数组的排序,但我们发现仍然有一些类,比如JDK或者第三方类库中的类,他们并没有实现Comparable接口,我们不方便修改源码,而且讲道理,我们也不应该修改这些类的源码。针对这些类型,我们又应该如何对他们进行排序呢?

       答案就是今天的Comparator接口,来,话不多说,直接上代码感受下社会Comparator哥的魅力。

     

import java.util.Arrays;
import java.util.Comparator;

/*
 *通用类型的两路归并算法实现
 */
public class GenericMergeSort {
    /**
     * 对数组array中start到end之间元素进行排序
     * @param array 待排序数组
     * @param start 排序起始索引
     * @param end 排序截止索引
     * @return 输出有序数组
     */
    public static <T> T[] sort(T[] array, int start, int end, Comparator<T> comparator) {
        int mid = (start + end) / 2;
        if (start < end) {
            // 左边有序
            sort(array, start, mid,comparator);
            // 右边有序
            sort(array, mid + 1, end,comparator);
            // 左右归并
            merge(array, start, mid, end,comparator);
        }
        return array;
    }

    public static <T> void merge(T[] array, int start, int middle, int end,Comparator<T> comparator) {
        //用于存储中间结果
        Object[] temp =  new Object[end - start + 1];

        //分别代表a,b,temp临时数组的下标指示器
        int i = start;
        int j = middle + 1;
        int k = 0;

        // 把较小的数先移到中间结果数组中
        while (i <= middle && j <= end) {
            if (comparator.compare(array[i],array[j])<0) {
                temp[k++] = array[i++];
            } else {
                temp[k++] = array[j++];
            }
        }

        //判定a数组是否有剩余,如果有将a数组剩余元素放入结果数组
        while (i <= middle) {
            temp[k++] = array[i++];
        }

        //判定b数组是否有剩余,如果有将b数组剩余元素放入结果数组
        while (j <= end) {
            temp[k++] = array[j++];
        }

        // 将中间结果写入到最终结果中
        for (int l = 0; l < temp.length; l++) {
            array[l + start] = (T) temp[l];
        }
    }

}
    对于任意需要排序的类型A,我们只需要实现一个Compator<A>,并在compare方法中实现相应的比较逻辑即可。友情提示:用Java 8的lambda表达式实现最佳。

    好了,本系列通用类型的两路归并实现就说到这儿,希望大家能真实地体会到面向对象编程和面向接口编程的魅力。

    created by 刘Sir

    

Dijkstra算法是一种用于在加权图中找到最短路径的算法,它可以处理没有负权边的图。算法的基本思想是,从源点开始,逐步增加到其他顶点的距离,直到找到最短路径为止。Dijkstra算法采用贪心策略,每次找到距离源点最近的一个未被访问的顶点,并更新其他顶点到源点的距离。 在Java实现Dijkstra算法通常需要使用优先队列来优化查找当前距离源点最近顶点的过程。以下是Dijkstra算法Java实现的一个简单例子: ```java import java.util.*; class Dijkstra { // 图的顶点数量 private static final int N = 9; // Dijkstra算法实现 public static void dijkstra(int[][] graph, int startVertex) { // 记录源点到每个顶点的最短路径 int[] dist = new int[N]; // 初始化距离数组,所有顶点距离设置为无穷大 Arrays.fill(dist, Integer.MAX_VALUE); // 用于标记顶点是否被访问过 boolean[] visited = new boolean[N]; // 起始点到自身的距离是0 dist[startVertex] = 0; // 用优先队列优化查找最小距离的顶点 PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.comparingInt(i -> dist[i])); // 将起始点加入优先队列 pq.add(startVertex); while (!pq.isEmpty()) { // 从优先队列中选出距离最小的顶点 int u = pq.poll(); // 如果这个顶点已经被访问过,跳过 if (visited[u]) continue; // 标记顶点为已访问 visited[u] = true; // 遍历所有邻接的顶点 for (int v = 0; v < N; v++) { // 如果顶点u到顶点v存在边,并且顶点v未被访问 if (graph[u][v] != 0 && !visited[v]) { // 计算源点通过顶点u到顶点v的路径长度 int newDist = dist[u] + graph[u][v]; // 如果新的路径长度小于当前记录的路径长度,则更新之 if (newDist < dist[v]) { dist[v] = newDist; // 将顶点v加入优先队列 pq.add(v); } } } } // 输出从源点到每个顶点的最短路径长度 for (int i = 0; i < N; i++) { System.out.println("Distance from vertex " + startVertex + " to vertex " + i + " is " + dist[i]); } } public static void main(String[] args) { // 示例图的邻接矩阵表示 int[][] graph = { {0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0} }; // 从顶点0开始计算最短路径 dijkstra(graph, 0); } } ``` 在这个例子中,`graph`是一个图的邻接矩阵表示,`dijkstra`方法实现了Dijkstra算法,`main`方法用于测试算法。请注意,这个例子假设图是用邻接矩阵表示的,并且顶点编号从0开始。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值