比Bubblesort慢的数量级(C ++)

时间:2016-04-28 18:49:45

标签: c++ sorting quicksort bubble-sort heapsort

我已经实现了heap数据结构,并使用它进行排序。我的理解是O(nlogn)复杂性。但是,与bubble sort相比,它慢了几个数量级 - 是的,我尝试为更大的数组运行它。我在SO(特别是thisthis)检查了一些答案,但仍然丢失了。有谁可以指出我在这里做错了什么,拜托?

结果是:

HEAP SORT: 12415690ns
QUICK SORT: 71ns
BUBBLE SORT: 541659ns

以下是代码:

main.cpp

#include <chrono>
#include <iostream>
#include <stdexcept>
#include <vector>

// #include "heap.cpp"
// #include "pqueue.cpp"
#include "sort.cpp"

using namespace std;
using namespace std::chrono;

template <class T>
void printVector (vector<T> A) {
    for (std::vector<int>::iterator it = A.begin(); it != A.end(); ++it) {
        std::cout << *it << ' ';
    }
    cout << endl;
}

template <class T>
vector<T> constructVector(int A[], std::size_t len, std::size_t num) {
    vector<T> res (A, A+len);
    for (std::size_t idx = 0; idx < num-1; ++idx) {
        res.push_back(A[idx%len]);
    }
    return res;
}

int main() {

    high_resolution_clock::time_point t1;
    high_resolution_clock::time_point t2;

    int a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
    std::size_t len = sizeof(a) / sizeof(int);
    vector<int> HEAP = constructVector<int>(a, len, 32000); // (a, a + sizeof(a) / sizeof(int));
    vector<int> QUICK = constructVector<int>(a, len, 32000); // (a, a + sizeof(a) / sizeof(int));
    vector<int> BUBBLE = constructVector<int>(a, len, 32000);

    // cout << "Original Array: "; printVector(HEAP);
    cout << "HEAP SORT: ";
    t1 = high_resolution_clock::now();
    heapsort(HEAP);
    t2 = high_resolution_clock::now();
    cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
    // cout << "New Array: "; printVector(HEAP);

    // cout << "Original Array: "; printVector(QUICK);
    cout << "QUICK SORT: ";
    t1 = high_resolution_clock::now();
    quicksort(QUICK, 0, QUICK.size());
    t2 = high_resolution_clock::now();
    cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
    // cout << "New Array: "; printVector(HEAP);

    // cout << "Original Array: "; printVector(QUICK);
    cout << "BUBBLE SORT: ";
    t1 = high_resolution_clock::now();
    bublesort(BUBBLE);
    t2 = high_resolution_clock::now();
    cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
    // cout << "New Array: "; printVector(HEAP);

}

sort.cpp

#ifndef __SORT_CPP_INCLUDED_
#define __SORT_CPP_INCLUDED_

#include <vector>
#include "heap.cpp"

template <class T>
void heapsort(std::vector<T> &A, bool increasing = true) {
    Heap<T> H(A, increasing);
    H.sort();
    A = H.get();
}

template <class T>
std::size_t partition(std::vector<T> &A, std::size_t p, std::size_t r) {
    T x = A[r-1];
    std::size_t i = p - 1;
    for (std::size_t j = p; j < r; ++j) {
        if (A[j] <= x) {
            ++i;
            A[i] ^= A[j];
            A[j] ^= A[i];
            A[i] ^= A[j];
        }
    }
    A[i+1] ^= A[r-1];
    A[r-1] ^= A[i+1];
    A[i+1] ^= A[r-1];

    return i + 1;
}

template <class T>
void quicksort(std::vector<T> &A, std::size_t p, std::size_t r) {
    if (p-1 < r) {
        std::size_t q = partition(A, p, r);
        quicksort(A, p, q);
        quicksort(A, q+1, r);
    }
}

template <class T>
void bublesort(std::vector<T> &A) {
    bool swapped = false; 
    do {
        swapped = false;
        for (std::size_t idx = 1; idx < A.size(); ++idx) {
            if (A[idx-1] > A[idx]) {
                // swap them
                A[idx] = A[idx-1];
                A[idx-1] = A[idx];
                A[idx] = A[idx-1];
                swapped = true;
            }
        }
    } while (swapped);
}
#endif

heap.cpp

#ifndef __HEAP_CPP_INCLUDED__
#define __HEAP_CPP_INCLUDED__

#include <vector>

template <class T>
class Heap {
public:
    Heap(bool maxHeap = true) : heap_size(0), max_heap(maxHeap) {}
    Heap(const std::vector<T> &a, bool maxHeap = true) : A(a),  max_heap(maxHeap) {
        if (maxHeap) this->build_max_heap(); else this->build_min_heap(); }
    ~Heap() {}

protected:
    std::vector<T> A;
    std::size_t heap_size;
    bool max_heap;

public:
    std::size_t parent(std::size_t idx) { return (idx - 1) >> 1; }
    std::size_t left(std::size_t idx) { return (idx << 1) + 1; }
    std::size_t right (std::size_t idx) { return (idx + 1) << 1; }

public:
    std::vector<T> get() { return A; }
    std::size_t size() { return heap_size; }

    void sort();

    void build_max_heap();
    void build_min_heap();

    void max_heapify(std::size_t idx);
    void min_heapify(std::size_t idx);
};

template <class T>
void Heap<T>::sort() {
    if (this->heap_size <= 0) return; // Already sorted or empty
    if (this->heap_size != this->A.size()){ // Not sorted and not heapified
        max_heap ? build_max_heap() : build_min_heap();
    }
    for (std::size_t idx = this->A.size()-1; idx > 0; --idx) {
        A[0] ^= A[idx];
        A[idx] ^= A[0];
        A[0] ^= A[idx];
        --this->heap_size;
        max_heap ? max_heapify(0) : min_heapify(0);
    }
}

template<class T>
void Heap<T>::build_max_heap() {
    this->heap_size = this->A.size();
    for (std::size_t idx = (this->A.size() - 1) >> 1; idx > 0; --idx)
        this->max_heapify(idx);
    this->max_heapify(0);
}

template<class T>
void Heap<T>::build_min_heap() {
    this->heap_size = this->A.size();
    for (std::size_t idx = (this->A.size()-1) >> 1; idx > 0; --idx)
        this->min_heapify(idx);
    this->min_heapify(0);
}


template <class T>
void Heap<T>::max_heapify(std::size_t idx) {
    std::size_t l = this->left(idx);
    std::size_t r = this->right(idx);
    std::size_t largest;

    if (l < this->heap_size && A[l] > A[idx]) largest = l;
    else largest = idx;

    if (r < this->heap_size && A[r] > A[largest]) largest = r;

    if (largest != idx) {
        this->A[idx] ^= this->A[largest];
        this->A[largest] ^= this->A[idx];
        this->A[idx] ^= this->A[largest];
        this->max_heapify(largest);
    }
}

template <class T>
void Heap<T>::min_heapify(std::size_t idx) {
    std::size_t l = this->left(idx);
    std::size_t r = this->right(idx);
    std::size_t smallest;
    // std::cout << "DEBUG: " << idx << std::endl;
    if (l < this->heap_size && A[l] < A[idx]) smallest = l;
    else smallest = idx;

    if (r < this->heap_size && A[r] < A[smallest]) smallest = r;

    if (smallest != idx) {
        this->A[idx] ^= this->A[smallest];
        this->A[smallest] ^= this->A[idx];
        this->A[idx] ^= this->A[smallest];
        this->min_heapify(smallest);
    }
}
#endif

1 个答案:

答案 0 :(得分:0)

  1. 您的冒泡排序不会交换,只能复制。这会使它更快一些。但不确定这个问题是如此之快。
  2. 您的Heap<T>制作了数组的副本。这可以解释缓慢。我猜你忘记了&
  3. 您应该注意到71ns排序32k阵列并不真实。你的快速排序从不排序任何东西。您可以使用std::sort获得可靠的快速排序。
  4. 在编译时已知太多,而且数字远非随机。在此类测试中切换到具有随机数的数组。