中值问题O(N)算法C++源码

本文介绍了一种高效的近似中位数算法,通过逐步缩小数据集并利用选择排序等方法来快速找到接近真实中位数的元素。该算法特别适用于大数据集,在保持计算效率的同时牺牲一定的精确度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

#include <iostream>

#include <cstdlib>

#include <ctime>

#include <algorithm>

using namespace std;

 

void swap(int A[], int i, int j) {

       if (i != j) {

            int t = A[i];

            A[i] = A[j];

            A[j] =t;

      }

}

 

int partition(int A[], int p, int r) {

    int x = A[r];

    int i = p - 1;

    for (int j = p; j <= r-1; j++) {

          if (A[j] <= x) {

                i++;

                swap(A, i, j);

          }

     }

 

     swap(A, i+1, r);

     return i+1;

}

 

int randomized_partition(int A[], int p, int r) {

     srand(time(NULL));

     int i = p + rand() % (r-p+1);

     swap(A, i, r);

     return partition(A, p, r);

}

 

int randomized_select(int A[], int p, int r, int i) {

    if (p == r) 

    return A[p];

    int q = randomized_partition(A, p, r);

    int k = q - p + 1;

    if (i == k)

         return A[q];

    else if (i < k)

         return randomized_select(A, p, q-1, i);

    else 

         return randomized_select(A, q+1, r, i-k);

}

 

void triplet_adjust(int A[], int i, int step) {

    int j = i + step;

    int k = i + 2 * step;

    if (A[i] < A[j]) {

    if (A[k] < A[i])

swap(A, i, j);

    else if (A[k] < A[j])

        swap(A, j, k);

    }

    else {

if (A[i] < A[k])

             swap(A, i, j);

else if (A[k] > A[j])

             swap(A, j, k);

     }

}

 

double mean(int A[], int n) {

      double f = A[0];

      for (int i = 1; i < n; i++)

             f += A[i];

      return f / n;

}

 

int approximate_median(int A[], int r) {

     int step = 1;

     int size = 1;

     int i;

 

    for (int j = 0; j < r; j++)

          size *= 3;

    for (int k = 0; k < r; k++) {

          i = (step - 1) / 2;

          while (i < size) {

                 triplet_adjust(A, i, step);

                 i += (3 * step);

          }

          step *= 3;

      }

 

      return A[(size-1)/2];

}

 

void selection_sort(int A[], int left, int size, int step) {

      int min;

      int i, j;

      for (i = left; i < left + (size-1) * step; i += step) {

              min = i;

              for (j = i+step; j < left + size; j += step) {

                     if (A[j] < A[min])

                     min = j;

              }

              swap(A, i, j);

        }

}

 

const int SORT_NUM_THRESHOD = 50;

 

int approximate_median_any_n(int A[], int size) {

      bool left_to_right = false;

      int left = 0;

      int step = 1;

      int i;

     while (size > SORT_NUM_THRESHOD) {

            left_to_right = !left_to_right;

            int rem = size % 3;

            if (left_to_right)

                   i = left;

            else

                   i = left + (3 + rem) * step;

            for (int j = 0; j < (size / 3 - 1); j++) {

                  triplet_adjust(A, i, step);

                  i += 3 * step;

            }

 

        if (left_to_right) 

             left += step;

        else {

             i = left;

             left += (1 + rem) * step;

        }

  

         selection_sort(A, i, 3 + rem, step);

 

         if (rem == 2) {

               if (left_to_right)

                       swap(A, i+step, i+2*step);

               else

                      swap(A, i+2*step, i+3*step);

           }

 

            step *= 3;

             size = size / 3;

}

 

selection_sort(A, left, size, step);

       return A[left + step * int( (size-1) / 2 )];

}

 

 

int main(int argc, char* argv[]) 

{

    const int DEFAULT_N = 1000000;

    int N;

 

      if (argc < 2) {

            N = DEFAULT_N;

     }

     else {

            N = atoi(argv[1]);

     }

 

cout << "N = " << N << endl;

clock_t t = clock();

cout << clock() << endl;

int* A = new int[N];

cout << clock() << endl;

srand(time(NULL));

for (int i=0; i<N; i++) {

A[i] = rand() % N;

}

 

clock_t t1 = clock();

cout << t1 << endl;

double avg = mean(A, N);

cout << avg << endl;

 

clock_t t2 = clock();

cout << t2 << endl;

int m = approximate_median_any_n(A, N);

cout << m << endl;

 

clock_t t3 = clock();

cout << t3 << endl;

m = randomized_select(A, 0, N-1, N/2);

cout << m << endl;

 

clock_t t4 = clock();

cout << t4 << endl;

 

std::sort(A, A+N);

m = A[N/2];

cout << m << endl;

 

clock_t t5 = clock();

cout << t5 << endl;

 

cout << endl;

 

double dt = (double) (t2-t1) / CLOCKS_PER_SEC;

cout << dt << "  " ;

dt = (double) (t3-t2) / CLOCKS_PER_SEC;

cout << dt << "  " ;

dt = (double) (t4-t3) / CLOCKS_PER_SEC;

cout << dt << "  " ;

dt = (double) (t5-t4) / CLOCKS_PER_SEC;

cout << dt << "  " ;

    cout << endl;

 

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值