1、快排算法 java
/** * quicksort to sort array * */ public class QuickSort { int partition(double a[], int low, int high) { double tmp = a[low]; int i = low, j = high; while (i < j) { while (i < j && a[j] >= tmp){ j--; } while (i < j && a[i] <= tmp){ i++; } swap(a, i, j); } a[low] = a[i]; a[i] = tmp; return i; } void swap(double a[], int i, int j) { double tmp = a[i]; a[i] = a[j]; a[j] = tmp; } void quickSort(double a[], int low, int high) { if (low < high) { int pos = partition(a, low, high); quickSort(a, low, pos - 1); quickSort(a, pos + 1, high); } } public static void main(String[] args) { QuickSort test = new QuickSort(); double a[] = {1d, 10d, 7d,9d,11d,1d,50d,3d}; test.quickSort(a, 0, a.length - 1); System.out.println(a); } }
2、求中位数算法
/** * 快排找中位数 * 思想:转化成找第K小的数 k = array.length / 2 + 1 * partition分成两边后 * 1、左边个数>K,则继续在左边找 * 2、左边个数<K,则在右边找,此时newK = oldK - 左边个数 * 3、当相等时,则partition得到的pos即是中位数,这种情况分成奇偶两种情况 * a、奇数时直接返回 * b、偶数时要找到该中位数左边区域的最大值 * 最大值分两种情况: * 1、该中位数所在迭代中左边还有数,则取左边的最大值 * 2、该中位数所在迭代中左边无值,则取上回分裂中将该中位数分到右边的分裂点,即程序中的prePart * */ public class QuieckSortMedium { private boolean bOdd;//是否奇偶数 private int kv;//k值 private double medium; int partition(double a[], int low, int high) { double tmp = a[low]; int i = low, j = high; while (i < j) { while (i < j && a[j] >= tmp){ j--; } while (i < j && a[i] <= tmp){ i++; } swap(a, i, j); } a[low] = a[i]; a[i] = tmp; return i; } void swap(double a[], int i, int j) { if(i == j){ return; } double tmp = a[i]; a[i] = a[j]; a[j] = tmp; } void findMedium(double a[]){ bOdd = a.length % 2 == 0; kv = a.length / 2 + 1; medium = 0; findK(a, 0, a.length - 1, kv, -1); } /** * 需求第K小 * @param a * @param low * @param high * @param k * @param prePart 上回分裂中将该中位数分到右边的分裂点 */ void findK(double a[], int low, int high, int k, int prePart){ if(low > high){ return; } int pos = partition(a, low, high); int left = pos - low + 1;//左边个数 if(k > left){//中位数在分裂点右边,将该分裂点作为下次迭代的prePart findK(a, pos + 1, high, k - left, pos); } else if(k < left){//中位数在分裂点左边,本次的prePart作为下次迭代的prePart findK(a, low, pos - 1, k, prePart); } else{ if(bOdd){//偶数时的中位数处理,取两个中位数的均值 double v1 = a[pos]; double v2 = 0; if(low >= pos){ v2 = a[prePart]; //左边无值时取prePart }else{ v2 = findMax(a, low, pos - 1);//左边有值时取左边最大值 } medium = (v1 + v2) / 2; }else{ medium = a[pos]; } } } double findMax(double a[], int low, int high){ double max = a[low]; for(int i = low + 1; i <= high; i ++){ if(a[i] > max){ max = a[i]; } } return max; } double getMedium(){ return medium; } }
3、扩展成求Java的任意对象数组的中位数
import java.util.ArrayList; import java.util.List; /** * 找中位数,使用快排找第K小数算法 * @author wangzejie * * @param <T> */ public class MediumFinder<T extends Comparable<T>> { private boolean bOdd;//是否奇偶数 private int kv;//第几大的值 private List<T> medium = new ArrayList<T>();//中位数数组 /** * 一次quicksort划分两边 * @param a * @param low * @param high * @return */ private int partition(T a[], int low, int high) { T tmp = a[low]; int i = low, j = high; while (i < j) { while (i < j && a[j].compareTo(tmp) >= 0){ j--; } while (i < j && a[i].compareTo(tmp) <= 0){ i++; } swap(a, i, j); } a[low] = a[i]; a[i] = tmp; return i; } /** * 交换数组两个位置的值 * @param a * @param i * @param j */ private void swap(T a[], int i, int j) { if(i == j){ return; } T tmp = a[i]; a[i] = a[j]; a[j] = tmp; } /** * 需求中位值 * @param a * @return 返回中位的T对象,当偶数时返回两点,奇数时返回一点 */ public List<T> findMedium(T a[]){ medium.clear(); if(a.length == 1){ medium.add(a[0]); }else if(a.length == 2){ medium.add(a[0]); medium.add(a[1]); }else{ bOdd = a.length % 2 == 0; kv = a.length / 2 + 1; findK(a, 0, a.length - 1, kv, -1); } return medium; } /** * 寻找第K少的值 * @param a * @param low * @param high * @param k * @param prePart */ private void findK(T a[], int low, int high, int k, int prePart){ if(low > high){ return; } int pos = partition(a, low, high); int left = pos - low + 1; if(k > left){ findK(a, pos + 1, high, k - left, pos); } else if(k < left){ findK(a, low, pos - 1, k, prePart); } else{ if(bOdd){ T v1 = a[pos]; T v2 = null; if(low >= pos){ v2 = a[prePart]; }else{ v2 = findMax(a, low, pos - 1); } medium.add(v1); medium.add(v2); }else{ medium.add(a[pos]); } } } /** * 寻找数组一定范围内的最大值 * @param a * @param low * @param high * @return */ private T findMax(T a[], int low, int high){ T max = a[low]; for(int i = low + 1; i <= high; i ++){ if(a[i].compareTo(max) > 0){ max = a[i]; } } return max; } } public class Point implements Comparable<Point> { private double lng; private double lat; private double value; public double getLng() { return lng; } public void setLng(double lng) { this.lng = lng; } public double getLat() { return lat; } public void setLat(double lat) { this.lat = lat; } public double getValue() { return value; } public void setValue(double value) { this.value = value; } @Override public int compareTo(Point o) { double t = this.value - o.value; if (t > 0) { return 1; } else if (t < 0) { return -1; } return 0; } }
相关推荐
从给定的文件标题、描述、标签以及部分内容来看,本篇文章将深入探讨快速排序(简称快排)算法的核心原理与实现细节。快速排序是一种高效的排序算法,由英国计算机科学家托尼·霍尔于1960年提出。其基本思想是通过一...
- **三数取中法**:在选择基准时,避免总是选取数组的第一个或最后一个元素,而是取中间三个数的中位数,这样能降低最坏情况出现的概率。 - **尾递归优化**:在某些实现中,可以优化递归调用,使其变为尾递归,减少...
### 冒泡、快排、插入、合并、选择排序算法集锦 #### 一、冒泡排序 **原理概述:** 冒泡排序是一种简单的排序算法,它重复地遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的...
常见的排序算法有冒泡排序、选择排序、快排、归并排序、堆排序等。这些算法的时间复杂度和空间复杂度各不相同,本文将对这些算法进行详细的介绍。 冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法,通过...
通常选择第一个或最后一个元素,但更优的选择方式是选取中位数,这可以减少平均情况下的比较次数。 2. **分区操作**:遍历数组,将小于基准的元素放在基准的左边,大于基准的放在右边。这样,基准就位于最终排序后...
实际实现时,可以考虑一些优化措施,比如三数取中法(取首、尾、中间三个元素的中位数作为基准),以减少最坏情况的发生;对于小规模数据,可以使用插入排序,因为插入排序在小规模数据上效率更高。 8. **使用示例...
1. **插入排序**:插入排序的基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。在未完成排序的序列中,从前往后遍历,将每个元素插入到已排序部分的正确位置。在这个过程中,...
在编程领域,排序算法是计算机科学中的核心概念,它们用于对数据进行有序排列。这里我们主要探讨三种经典的排序算法:冒泡排序、快速排序和堆排序,并且它们都是使用C++语言实现的。这些排序算法各有特点,适用于...
实验中,你需要实现这三个排序算法,并理解它们的物理存储结构以及如何用高级语言(如C语言)实现。理解这些排序算法的性能分析方法也很重要,比如快速排序的平均时间复杂度为O(nlogn),但最坏情况下为O(n^2),而堆...
- **三数取中**:选取枢轴时,可以选取待排序序列的第一个、最后一个和中间元素的中位数,以减少平均情况下的分割不均。 - **随机化选择枢轴**:随机选取待排序序列中的一个元素作为枢轴,可以避免最坏情况的发生,...
- **三数取中法**:选择数组首、尾、中间三个元素的中位数作为基准,可以进一步提高划分的均匀性。 - **尾递归优化**:当子数组大小小于某个阈值时,可以改用插入排序,因为对于小数组,插入排序可能更快。 通过...
改进的冒泡排序通常包括设置标志位来检测是否已经完成排序,以及添加一个提前退出循环的条件,当某次遍历没有发生交换时,说明数组已有序。 2. **插入排序**:插入排序的工作原理是将数组分为已排序和未排序两部分...
例如,给 20 亿个不重复的 unsigned int 的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那 40 亿个数当中,并且所耗内存尽可能的少?可以使用 Bitmap 算法来解决这个问题。 在 Java 中,可以使用 ...
### 排序算法知识点 根据提供的代码片段及标题、描述,可以提炼出以下关于排序算法的知识点: #### 1. 插入排序(Insert Sort) 插入排序是一种简单直观的比较排序算法。它的工作原理是通过构建有序序列,对于未...
例如,如果当前处理的是个位,那么将所有个位为3的数放入“3”桶中。 3. 重新排列:收集每个桶中的元素,并按照顺序放置回原数组。这样,个位已经按照大小顺序排列好了。 4. 对下一位进行相同的操作,直到所有的位...
在设计PCB表时,对于“可强占的优先数调度算法”,我们需要额外考虑进程的优先级和当前状态,以便在运行过程中能够根据需要中断正在执行的进程,转而执行优先级更高的进程。这需要在PCB中包含优先级字段以及一个标志...
在IT领域,排序算法是计算机科学中至关重要的一个部分,特别是在数据结构与算法设计中。本文将详尽探讨数据结构中的各种排序算法及其原理、性能分析,并附带一份详细的报告,帮助读者深入理解这些核心概念。 一、...
8. **快排优化**:三向切分快排能处理大量重复元素的情况,避免过多的递归。当子问题规模较小,可用插入排序替代递归。 9. **链表反转**:通过三个指针,分别指向当前节点、前一个节点和下一个节点,迭代完成链表...