Skip to content

Commit d9a7ee7

Browse files
committed
update heap sort
1 parent b8a15df commit d9a7ee7

File tree

10 files changed

+768
-0
lines changed

10 files changed

+768
-0
lines changed

heap-sort/03-MaxHeap-Shift-Down/main

-19.6 KB
Binary file not shown.

heap-sort/05-Heap-Sort/Heap.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//
2+
// Created by 3zz.
3+
//
4+
5+
#ifndef INC_06_HEAP_SORT_HEAP_H
6+
#define INC_06_HEAP_SORT_HEAP_H
7+
8+
#include <algorithm>
9+
#include <cassert>
10+
11+
using namespace std;
12+
13+
template <typename Item>
14+
class MaxHeap
15+
{
16+
17+
private:
18+
Item *data;
19+
int count;
20+
int capacity;
21+
22+
void shiftUp(int k)
23+
{
24+
while (k > 1 && data[k / 2] < data[k])
25+
{
26+
swap(data[k / 2], data[k]);
27+
k /= 2;
28+
}
29+
}
30+
31+
void shiftDown(int k)
32+
{
33+
while (2 * k <= count)
34+
{
35+
int j = 2 * k;
36+
if (j + 1 <= count && data[j + 1] > data[j])
37+
j++;
38+
if (data[k] >= data[j])
39+
break;
40+
swap(data[k], data[j]);
41+
k = j;
42+
}
43+
}
44+
45+
public:
46+
// 构造函数, 构造一个空堆, 可容纳capacity个元素
47+
MaxHeap(int capacity)
48+
{
49+
data = new Item[capacity + 1];
50+
count = 0;
51+
this->capacity = capacity;
52+
}
53+
54+
// 构造函数, 通过一个给定数组创建一个最大堆
55+
// 该构造堆的过程, 时间复杂度为O(n)
56+
MaxHeap(Item arr[], int n)
57+
{
58+
data = new Item[n + 1];
59+
capacity = n;
60+
61+
for (int i = 0; i < n; i++)
62+
data[i + 1] = arr[i];
63+
count = n;
64+
65+
for (int i = count / 2; i >= 1; i--)
66+
shiftDown(i);
67+
}
68+
69+
~MaxHeap()
70+
{
71+
delete[] data;
72+
}
73+
74+
// 返回堆中的元素个数
75+
int size()
76+
{
77+
return count;
78+
}
79+
80+
// 返回一个布尔值, 表示堆中是否为空
81+
bool isEmpty()
82+
{
83+
return count == 0;
84+
}
85+
86+
// 像最大堆中插入一个新的元素 item
87+
void insert(Item item)
88+
{
89+
assert(count + 1 <= capacity);
90+
data[count + 1] = item;
91+
shiftUp(count + 1);
92+
count++;
93+
}
94+
95+
// 从最大堆中取出堆顶元素, 即堆中所存储的最大数据
96+
Item extractMax()
97+
{
98+
assert(count > 0);
99+
Item ret = data[1];
100+
swap(data[1], data[count]);
101+
count--;
102+
shiftDown(1);
103+
return ret;
104+
}
105+
106+
// 获取最大堆中的堆顶元素
107+
Item getMax()
108+
{
109+
assert(count > 0);
110+
return data[1];
111+
}
112+
};
113+
114+
#endif //INC_06_HEAP_SORT_HEAP_H

heap-sort/05-Heap-Sort/HeapSort.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// Created by liuyubobobo on 8/16/16.
3+
//
4+
5+
#ifndef INC_06_HEAP_SORT_HEAPSORT_H
6+
#define INC_06_HEAP_SORT_HEAPSORT_H
7+
8+
#include "Heap.h"
9+
10+
using namespace std;
11+
12+
// heapSort1, 将所有的元素依次添加到堆中, 在将所有元素从堆中依次取出来, 即完成了排序
13+
// 无论是创建堆的过程, 还是从堆中依次取出元素的过程, 时间复杂度均为O(nlogn)
14+
// 整个堆排序的整体时间复杂度为O(nlogn)
15+
template <typename T>
16+
void heapSort1(T arr[], int n)
17+
{
18+
19+
MaxHeap<T> maxheap = MaxHeap<T>(n);
20+
for (int i = 0; i < n; i++)
21+
maxheap.insert(arr[i]);
22+
23+
for (int i = n - 1; i >= 0; i--)
24+
arr[i] = maxheap.extractMax();
25+
}
26+
27+
// heapSort2, 借助我们的heapify过程创建堆
28+
// 此时, 创建堆的过程时间复杂度为O(n), 将所有元素依次从堆中取出来, 实践复杂度为O(nlogn)
29+
// 堆排序的总体时间复杂度依然是O(nlogn), 但是比上述heapSort1性能更优, 因为创建堆的性能更优
30+
template <typename T>
31+
void heapSort2(T arr[], int n)
32+
{
33+
34+
MaxHeap<T> maxheap = MaxHeap<T>(arr, n);
35+
for (int i = n - 1; i >= 0; i--)
36+
arr[i] = maxheap.extractMax();
37+
}
38+
39+
#endif //INC_06_HEAP_SORT_HEAPSORT_H
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Created by 3zz.
3+
//
4+
5+
#ifndef INC_06_HEAP_SORT_INSERTIONSORT_H
6+
#define INC_06_HEAP_SORT_INSERTIONSORT_H
7+
8+
#include <iostream>
9+
#include <algorithm>
10+
11+
using namespace std;
12+
13+
template <typename T>
14+
void insertionSort(T arr[], int n)
15+
{
16+
17+
for (int i = 1; i < n; i++)
18+
{
19+
20+
T e = arr[i];
21+
int j;
22+
for (j = i; j > 0 && arr[j - 1] > e; j--)
23+
arr[j] = arr[j - 1];
24+
arr[j] = e;
25+
}
26+
27+
return;
28+
}
29+
30+
// 对arr[l...r]范围的数组进行插入排序
31+
template <typename T>
32+
void insertionSort(T arr[], int l, int r)
33+
{
34+
35+
for (int i = l + 1; i <= r; i++)
36+
{
37+
38+
T e = arr[i];
39+
int j;
40+
for (j = i; j > l && arr[j - 1] > e; j--)
41+
arr[j] = arr[j - 1];
42+
arr[j] = e;
43+
}
44+
45+
return;
46+
}
47+
48+
#endif //INC_06_HEAP_SORT_INSERTIONSORT_H

heap-sort/05-Heap-Sort/MergeSort.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// Created by liuyubobobo on 8/11/16.
3+
//
4+
5+
#ifndef INC_06_HEAP_SORT_MERGESORT_H
6+
#define INC_06_HEAP_SORT_MERGESORT_H
7+
8+
#include <iostream>
9+
#include <algorithm>
10+
#include "InsertionSort.h"
11+
12+
using namespace std;
13+
14+
// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
15+
// 其中aux为完成merge过程所需要的辅助空间
16+
template <typename T>
17+
void __merge(T arr[], T aux[], int l, int mid, int r)
18+
{
19+
20+
// 由于aux的大小和arr一样, 所以我们也不需要处理aux索引的偏移量
21+
// 进一步节省了计算量:)
22+
for (int i = l; i <= r; i++)
23+
aux[i] = arr[i];
24+
25+
// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
26+
int i = l, j = mid + 1;
27+
for (int k = l; k <= r; k++)
28+
{
29+
if (i > mid)
30+
{ // 如果左半部分元素已经全部处理完毕
31+
arr[k] = aux[j];
32+
j++;
33+
}
34+
else if (j > r)
35+
{ // 如果右半部分元素已经全部处理完毕
36+
arr[k] = aux[i];
37+
i++;
38+
}
39+
else if (aux[i] < aux[j])
40+
{ // 左半部分所指元素 < 右半部分所指元素
41+
arr[k] = aux[i];
42+
i++;
43+
}
44+
else
45+
{ // 左半部分所指元素 >= 右半部分所指元素
46+
arr[k] = aux[j];
47+
j++;
48+
}
49+
}
50+
}
51+
52+
// 使用优化的归并排序算法, 对arr[l...r]的范围进行排序
53+
// 其中aux为完成merge过程所需要的辅助空间
54+
template <typename T>
55+
void __mergeSort(T arr[], T aux[], int l, int r)
56+
{
57+
// 对于小规模数组, 使用插入排序
58+
if (r - l <= 15)
59+
{
60+
insertionSort(arr, l, r);
61+
return;
62+
}
63+
int mid = (l + r) / 2;
64+
__mergeSort(arr, aux, l, mid);
65+
__mergeSort(arr, aux, mid + 1, r);
66+
67+
// 对于arr[mid] <= arr[mid+1]的情况,不进行merge
68+
// 对于近乎有序的数组非常有效,但是对于一般情况,有一定的性能损失
69+
if (arr[mid] > arr[mid + 1])
70+
__merge(arr, aux, l, mid, r);
71+
}
72+
73+
template <typename T>
74+
void mergeSort(T arr[], int n)
75+
{
76+
77+
// 在 mergeSort中, 我们一次性申请aux空间,
78+
// 并将这个辅助空间以参数形式传递给完成归并排序的各个子函数
79+
T *aux = new T[n];
80+
__mergeSort(arr, aux, 0, n - 1);
81+
delete[] aux; // 使用C++, new出来的空间不要忘记释放掉:)
82+
}
83+
84+
#endif //INC_06_HEAP_SORT_MERGESORT_H

heap-sort/05-Heap-Sort/QuickSort.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// Created by liuyubobobo on 8/11/16.
3+
//
4+
5+
#ifndef INC_06_HEAP_SORT_QUICKSORT_H
6+
#define INC_06_HEAP_SORT_QUICKSORT_H
7+
8+
#include <iostream>
9+
#include <ctime>
10+
#include <algorithm>
11+
#include "InsertionSort.h"
12+
13+
using namespace std;
14+
15+
// 对arr[l...r]部分进行partition操作
16+
// 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
17+
template <typename T>
18+
int _partition(T arr[], int l, int r)
19+
{
20+
// 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
21+
swap(arr[l], arr[rand() % (r - l + 1) + l]);
22+
T v = arr[l];
23+
int j = l;
24+
for (int i = l + 1; i <= r; i++)
25+
if (arr[i] < v)
26+
{
27+
j++;
28+
swap(arr[j], arr[i]);
29+
}
30+
swap(arr[l], arr[j]);
31+
return j;
32+
}
33+
34+
// 对arr[l...r]部分进行快速排序
35+
template <typename T>
36+
void _quickSort(T arr[], int l, int r)
37+
{
38+
// 对于小规模数组, 使用插入排序进行优化
39+
if (r - l <= 15)
40+
{
41+
insertionSort(arr, l, r);
42+
return;
43+
}
44+
int p = _partition(arr, l, r);
45+
_quickSort(arr, l, p - 1);
46+
_quickSort(arr, p + 1, r);
47+
}
48+
49+
template <typename T>
50+
void quickSort(T arr[], int n)
51+
{
52+
srand(time(NULL));
53+
_quickSort(arr, 0, n - 1);
54+
}
55+
56+
#endif //INC_06_HEAP_SORT_QUICKSORT_H

0 commit comments

Comments
 (0)