八大排序算法


排序算法

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;
    }
}

文章作者: AllenMirac
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AllenMirac !
  目录