选择排序,依次找到数据集N、N-1、N-2、....中比它大/小的最大/最小者,最终达到全部数据有序。
1、选择排序:
直接的依次找到数据集合N、N-1、N-2.....的最大/最小者形成排序,非常好理解。选择排序可能是和冒泡排序一样,最直观能想到的排序方法。
显然选择排序和冒泡排序一样,无所谓最好、最坏、平均,选择排序的时间复杂度 = O(N - 1) + O(N - 2) + ...... + O(1) -> O(N * N)
另外很显然选择排序是稳定的排序。
空间复杂度:可以认为几乎没有
select.h(类声明):
#include <iostream>
#include <vector>
template<class T> class selsort {
std::vector<T> data;
public:
selsort(T *_data, int size);
selsort(std::vector<T> _data);
~selsort(){data.clear();}
void ssort();
void show(bool direct);
};
select_func.h(类实现):
#include "select.h"
template<class T> selsort<T>::selsort (T *_data, int size) {
for (int i = 0; i < size; i++) {
data.push_back(_data[i]);
}
ssort();
}
template<class T> selsort<T>::selsort (std::vector<T> _data) {
data = _data;
ssort();
}
template<class T> void selsort<T>::ssort () {
for (int i = 0; i < data.size() - 1; i++) {
int min = i;
for (int j = i + 1; j < data.size() - 1; j++) {
if (data[j] <= data[min]) {
min = j;
}
}
T minval = data[min];
data[min] = data[i];
data[i] = minval;
}
}
template<class T> void selsort<T>::show (bool direct) {
if (direct) {
for (int i = 0; i < data.size(); i++) {
std::cout << data[i];
if (i != data.size() - 1) {
std::cout << ", ";
}
}
} else {
for (int i = data.size() - 1; i >= 0; i--) {
std::cout << data[i];
if (i != 0) {
std::cout << ", ";
}
}
}
std::cout << std::endl;
}
select.cpp(测试程序):
#include "select_func.h"
#include <stdlib.h>
int main () {
int *testdata = new int[sizeof(int) * 30];
srand((int)time(0));
for (int i = 0; i < 30; i++) {
testdata[i] = rand() % 100;
}
selsort<int> selsorter(testdata, 30);
selsorter.show(1);
delete []testdata;
return 0;
}
2、堆排序:
二叉堆本身可参考前面的文章:堆(二叉堆)
堆排序其实过程上和上面的选择排序是一模一样的,只是堆在创建后,堆顶数据已经是当前数据集的最大/小者,然后每次交换堆顶和尚未排序的堆底数据,然后对剩余的数据进行堆排序,这样就依次保证了堆底到堆顶的数据是逐渐排序了的。
因为堆本质是二叉树,所以堆排序比上面的选择排序的最大改进是,每次寻找最大/最小元素的效率由O(X)降低为O(logX),所以堆排序的时间复杂度是O(Nl * ogN),最差、平均、最佳都认为是O(N * logN)。
但是堆排序要考虑创建堆的O(N) + N/2 * O(logN)的时间开销。
堆排序也不稳定,原始排在后面的同值元素,堆排序后可能会在前面。
空间复杂度:可以认为几乎没有
heap.h(类声明):
#include <vector>
template<class T> class heapsort {
std::vector<T> data;
int lchild(int i){return i * 2;}
int rchild(int i){return i * 2 + 1;}
int parent(int i){return i/2;}
public:
heapsort(T *data, int size);
heapsort(std::vector<T> _data);
~heapsort(){data.clear();}
void adjust(int i, int size);
void hsort();
void show(bool direct);
};
heap_func.h(类定义):
#include "heap.h"
#include <iostream>
template<class T> heapsort<T>::heapsort (T *_data, int size) {
data.push_back(_data[0]);
for (int i = 0; i < size; i++) {
data.push_back(_data[i]);
}
for (int i = data.size()/2; i >= 1; i--) {
adjust(i, data.size() - 1);
}
}
template<class T> heapsort<T>::heapsort (std::vector<T> _data) {
data.push_back(_data[0]);
for (int i = 0; i < _data.size(); i++) {
data.push_back(_data[i]);
}
for (int i = data.size()/2; i >= 1; i--) {
adjust(i, data.size() - 1);
}
}
template<class T> void heapsort<T>::adjust (int i, int size) {
int l = lchild(i), r = rchild(i), maxidx = i;
if (i <= size/2) {
if (l < data.size() && data[l] > data[maxidx]) {
maxidx = l;
}
if (r < data.size() && data[r] > data[maxidx]) {
maxidx = r;
}
if (maxidx != i) {
T ival = data[i];
data[i] = data[maxidx];
data[maxidx] = ival;
adjust(maxidx, size);
}
}
}
template<class T> void heapsort<T>::hsort () {
for (int i = data.size() - 1; i >= 1; i--) {
T lastval = data[i];
data[i] = data[1];
data[1] = lastval;
adjust(1, i - 1);
}
}
template<class T> void heapsort<T>::show (bool direct) {
if (direct) {
for (int i = 1; i < data.size(); i++) {
std::cout << data[i];
if (i != data.size() - 1) {
std::cout << ", ";
}
}
} else {
for (int i = data.size() - 1; i >= 1; i--) {
std::cout << data[i];
if (i != 1) {
std::cout << ", ";
}
}
}
std::cout << std::endl;
}
heap.cpp(测试程序):
#include "heap_func.h"
#include <stdlib.h>
int main () {
int *testdata = new int[sizeof(int) * 30];
srand((int)time(0));
for (int i = 0; i < 30; i++) {
testdata[i] = rand() % 100;
}
heapsort<int> heapsorter(testdata, 30);
heapsorter.show(1);
heapsorter.hsort();
heapsorter.show(1);
delete []testdata;
return 0;
}