排序算法
1、冒泡排序
template<typename T>
void BubbleSort(T a[], int len){
for(int i=0; i<len; i++){
for(int j=0; j<len-i-1; j++){
if(a[j]>a[j+1])
{
swap(a[j], a[j+1]);
}
}
}
}
2、选择排序
template<typename T>
void SelectSort(T arr[], int len){
for(int i=0; i<len; i++){
int min=i;
for(int j=i+1; j<len; j++){
if(arr[j]<arr[min]){
min=j;
}
}
swap(arr[i], arr[min]);
}
}
3、插入排序
template<typename T>
void InsertSort(T arr[], int len){
for(int i=1; i<len; i++){
int key=arr[i];
int j=i-1;
while(j>=0 && key<arr[j]){
arr[j+1]=arr[j];
j--;
}
arr[j+1]=key;
}
}
4、希尔排序
template<typename T>
void ShellSort(T arr[], int len){
int gap=1;
while(gap<len/3){
gap=gap*3+1;
}
while(gap>=1){
for(int i=gap; i<len; i++){
for(int j=i; j>gap && arr[j]<arr[j-gap]; j-=gap){
swap(arr[j], arr[j-gap]);
}
}
gap/=3;
}
}
5、快速排序
void quickSort(int a[], int l, int r){
if (l < r) {
int i,j,x;
i = l;
j = r;
x = a[i];
while (i < j) {
while(i < j && a[j] > x)
j--; // 从右向左找第一个小于x的数
if(i < j)
a[i++] = a[j];
while(i < j && a[i] < x)
i++; // 从左向右找第一个大于x的数
if(i < j)
a[j--] = a[i];
}
a[i] = x;// 将分割点放到正确位置
quickSort(a, l, i-1); /* 递归调用 */
quickSort(a, i+1, r); /* 递归调用 */
}
}
6、堆排序
void sift_down(int arr[], int start, int end){
int parent = start;
int child = 2*start+1;
while(child<=end){
if(child+1<=end && arr[child]<arr[child+1])
child++;
if(arr[parent]>arr[child])
return ;
else{
swap(arr[parent], arr[child]);
//往下调整
parent=child;
child=2*parent+1;
}
}
}
void heap_sort(int arr[], int len){
//调整为大根堆,从最后一个父元素开始(len-1-1)/2
for(int i=(len-1-1)/2; i>=0; i--) sift_down(arr, i, len-1);
//将堆的根(最大值)掉换到最后一个元素(从小到大排序),在重新调整为大根堆
for(int i=len-1; i>=0; i--){
swap(arr[0], arr[i]);
sift_down(arr, 0, i-1);
}
}
7、归并排序
一半一半砍开来,砍成只有两个元素之后,归并。
template<typename T>
void merge_sort1(T arr[], int len) {
T* a = arr;
T* b = new T[len];
for (int seg = 1; seg < len; seg += seg) {//区间长度
for (int start = 0; start < len; start += seg + seg) {
int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
int k = low;
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
while (start1 < end1)
b[k++] = a[start1++];
while (start2 < end2)
b[k++] = a[start2++];
}
T* temp = a;
a = b;
b = temp;
}
if (a != arr) {//这里没有看懂
for (int i = 0; i < len; i++)
b[i] = a[i];
b = a;
}
delete[] b;
}
8、桶排序
将数据放到到各个桶中,在插入数据的时候每个桶的数据保持有序,所以每个桶相当于是一个有序链表。最后将各个桶合并起来,即将各个链表Merge,形成一个有序的整体。
#include<iterator>
#include<iostream>
#include<vector>
using namespace std;
const int BUCKET_NUM = 10;// 桶的个数
/**
*链表结构体
*/
struct ListNode{
explicit ListNode(int i=0):mData(i),mNext(NULL){}
ListNode* mNext;
int mData;
};
/**
* 插入的时候是有序的,返回值是头节点
*/
ListNode* insert(ListNode* head,int val){
ListNode dummyNode;
ListNode *newNode = new ListNode(val);
ListNode *pre,*curr;
dummyNode.mNext = head;
pre = &dummyNode;
curr = head;
while(NULL!=curr && curr->mData<=val){
pre = curr;
curr = curr->mNext;
}
newNode->mNext = curr;
pre->mNext = newNode;
return dummyNode.mNext;
}
/**
* 将两个链表合并,合并后仍然保持有序
*/
ListNode* Merge(ListNode *head1,ListNode *head2){
ListNode dummyNode;
ListNode *dummy = &dummyNode;
while(NULL!=head1 && NULL!=head2){
if(head1->mData <= head2->mData){
dummy->mNext = head1;
head1 = head1->mNext;
}else{
dummy->mNext = head2;
head2 = head2->mNext;
}
dummy = dummy->mNext;
}
if(NULL!=head1) dummy->mNext = head1;
if(NULL!=head2) dummy->mNext = head2;
return dummyNode.mNext;
}
/**
* 桶排序主体部分
*/
void BucketSort(int n,int arr[]){
vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));// 存的是每个桶的头节点,一个桶相当于是一个有序链表
for(int i=0;i<n;++i){
int index = arr[i]/BUCKET_NUM; // 看要将数据放在哪个桶里面
ListNode *head = buckets.at(index);// 局部变量
buckets.at(index) = insert(head,arr[i]);// 插入桶中
}
ListNode *head = buckets.at(0); // 初始值是第0个桶
for(int i=1;i<BUCKET_NUM;++i){
head = Merge(head,buckets.at(i)); // 将两个桶合并
}
for(int i=0;i<n;++i){
arr[i] = head->mData;
head = head->mNext;
}
}
9、折半插入排序
template <typename T>
void insertSort1(vector<T> &v){
int n=v.size();
for(int i=1; i<n; i++){
int l=0, r=i-1;
T key=v[i];
int mid;
while(l<=r){
mid=(l+r)/2;
if(key < v[mid]) r=mid-1;
else l=mid+1;
//寻找第一个大于key的位置,所以直接使用else,<=的元素都不需要管
}
int k;
for(k=i-1; k>r; k--) v[k+1]=v[k];
v[k+1]=key;
}
}