1. 程式人生 > >排序知識點小結1-手寫堆排序及STL實現

排序知識點小結1-手寫堆排序及STL實現

首先是造輪子:

// maximum heap based on integer type
#include <bits/stdc++.h>
using namespace std;
const int MAX_SIZE = 100000;
int heap[MAX_SIZE], result[MAX_SIZE];
int size;
void init(){ 
	memset(heap, 0, sizeof(heap));
	memset(result, 0, sizeof(result));
}
bool is_leaf(int pos){
	return pos > size / 2 - 1; // n/2 - 1 has been proved to be the last branch node in the tree 
}
void swap(int a, int b){
	int temp = heap[a];
	heap[a] = heap[b];
	heap[b] = temp;
}
bool is_legal(int pos){
	return pos <= size - 1;
}
void sift_down(int pos){
	int left, right;
	while(!is_leaf(pos)){
		left = 2 * pos + 1;
		right = 2 * pos + 2;
		if(is_legal(right)){  // node have both left child and right child
			if(heap[pos] < max(heap[left], heap[right])){
				if(heap[left] == max(heap[left], heap[right])){
					swap(pos, left);
					pos = left;
				}
				else{
					swap(pos, right);
					pos = right;
				}
			}
			else{
				break;
			}
		}
		else if(is_legal(left)){  // node just have left child
			if(heap[pos] < heap[left]){
				swap(pos, left);
				pos = left;
			}
			else{
				break;
			}
		}
		else{ // node have no left child or right child
			break;
		}
	}
}
void build_heap(int *arr){
	for(int i = 0 ; i < size ; i++){
		heap[i] = arr[i];
	}
	for(int i = size / 2 - 1 ; i >= 0 ; i--){
		sift_down(i);
	}
}
//when there is just one num in the heap, then for sift_down function, 1 / 2 - 1 = -1; 
int removefirst(){
	int temp = heap[0];
	swap(0, size - 1);
	size--;
	sift_down(0);
	return temp;
}
void heap_sort(int* arr){
	build_heap(arr);
	for(int i = size - 1 ; i >= 0 ; i--)
		result[i] = removefirst();
}
int main(){
	cout << "Enter the size of the list: ";
	cin >> size; // the size of the heap
	int max_size = size;
	init();
	int *a = new int[size];
	cout << "Enter n numbers: ";
	for(int i = 0 ; i < max_size ; i++){
		cin >> 	a[i];
	}
	heap_sort(a);
	for(int i = 0 ; i < max_size ; i++){
		cout << result[i] << " ";
	}
	return 0;
}

吐槽下,shaffer那本書真的有毒,就用來學習下思想,各種邊界情況是不會有限制的

但個人挺喜歡裡面的函式設計,命名和使用非常清晰易懂

然後是STL實現:

預備知識:STL裡面的priority_queue

#include <bits/stdc++.h>
using namespace std;
struct Fish {
	string color;
	int weight;
	Fish() {}
	Fish(string c, int w) {color = c; weight = w;}
	bool operator < (const Fish & f) const {
		return weight > f.weight;
	}
};
//Here, we define the fish with lower weight has supreme privilage 
int main(){
	priority_queue <Fish> q;
	Fish f1("red", 100);
	Fish f2("pink", 140);
	Fish f3("blue", 99);
	q.push(f1);
	q.push(f2);
	q.push(f3);
	Fish temp;
	while(!q.empty()){
		temp = q.top();
		q.pop();
		cout << temp.color << " : " << temp.weight << endl;
	}
	return 0;
}

執行結果:

然後藉助這個STL容器的過載可以實現堆排序

#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue <int> q;
	int a[10] = {1,3,4,5,6,7,8,9,20,2};
	for(int i = 0 ; i < 10 ; i++){
		q.push(a[i]);
	}
	int temp = 0;
	while(!q.empty()){
		temp = q.top();
		cout << temp << " ";
		q.pop();
	}
	return 0;
}

執行結果:

當然,如果不想使用預設的值大的優先,可以過載如下:

#include<bits/stdc++.h>
using namespace std;
struct Num{
	int num;
	Num(){};
	Num(int n){
		num = n;
	}
	bool operator < (const Num & another) const{
		return num > another.num;
	}
};
int main(){
	priority_queue <Num> q;
	int a[10] = {1,3,4,5,6,7,8,9,20,2};
	for(int i = 0 ; i < 10 ; i++){
		q.push(Num(a[i]));
	}
	Num temp;
	while(!q.empty()){
		temp = q.top();
		cout << temp.num << " ";
		q.pop();
	}
	return 0;
}

輸出結果: