常见排序方法

插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序相关信息:

以下均已C++为例:

计数排序

//以投票(洛谷P1271)为例
#include<iostream>
using namespace std;
int main()
{
	int n = 0, m = 0,temp=0;
	int a[9999]={0};
	cin >> n >> m;//输入候选人(n)投票数(m)
	for (int i = 0; i < m; ++i)
	{
		cin >> temp;
		a[temp]++;
	}
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 0; j < a[i]; ++j)
		{
			cout << i << " ";
		}
	}
	cout << endl;
	system("pause");
	return 0;
}

选择排序

#include<iostream>
using namespace std;
int main()
{
	int n = 0;
	cin >> n;//输入数据数
	int a[999]={0};//定义数组
	for (int m = 0; m < n; ++m)//输入数据
	{
		cin >> a[m];
	}
	for (int i = 0; i < n-1; ++i)
	{
		for (int j =i+1; j < n; ++j)
		{
			if (a[j] < a[i])
			{
				int temp = a[j];
				a[j] = a[i];
				a[i] = temp;
			}
		}
	}
	for (int w = 0; w < n; ++w)//打印排列好的数据
	{
		cout << a[w]<<" ";
	}
	system("pause");
	return 0;
}

冒泡排序

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;//输入数据数
	int a[999] = { 0 };
	for (int o = 0; o < n; ++o)//输入数据
	{
		cin >> a[o];
	}
	for (int i = 0; i < n-1; ++i)
	{
		for (int j = 0; j < n - i - 1; ++j)
		{
			if (a[j]>a[j+1])
			{
			  int temp = a[j];
			  a[j] = a[j+1];
			  a[j+1] = temp;
			}
		}
	}
	for (int w = 0; w < n; ++w)//打印排列好的数据
	{
		cout << a[w]<<" ";
	}
	system("pause");
	return 0;
}

快速排序

void qsort(int a[], int l, int r)//引用数组的地址
{
	int i = l, j = r, flag = a[(l + r) / 2], tmp;
	do 
	{
		while (a[i] < flag)i++;//从左找比基准数大的数
		while (a[j] > flag)j--;//从右找比基准数小的数
		if (i <= j)
		{
			//交换
			tmp == a[i];
			a[i] = a[j];
			a[j] = tmp;
			i++;
			j--;
		}
	} while (i <= j)
		if (l < j)
			qsort(a, l, j);
	    if (i < r)
		    qsort(a, i, r);
}

下面这种虽程序框架和快速排序几乎一模一样,但梅西处理的区间长度期望下都会减半,所以是线性复杂度(来源:《深入浅出程序设计竞赛》)

int ans = 0,k;//记录答案,以及求第k小。k是已知值,比如在main函数中赋值过
void findkth(int a[], int l, int r)//引入数组的地址
{
	if(l == r)
	{
		ans = a[l];//区间长度为1时,记录答案
		return;
    }
	int i = l, j = r, flag = a[(l + r) / 2], tmp;
	do {
		while (a[i] < flag)++i;//从左找比哨兵大的数
		while (a[i] > flag)j--;//从右找比哨兵大的数
		if (i <= j)
		{
			//交换
			tmp= a[i];
			a[i] = a[j];
			a[j] = tmp;
		}
	} while (i <= j);

	if (k <= j)findkth(a, l, j);//第k小的数字在左区间
	else if (i <= k)findkth(a, i, r);//第k小的数字在右区间
	else findkth(a, j + 1, i - 1);//第k小的数字即不在左区间,也不在右区间
}

插入排序:

void insertion_sort(int 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;
        }
}

希尔排序:

template<typename T>
void shell_sort(T array[], int length) {
    int h = 1;
    while (h < length / 3) {
        h = 3 * h + 1;
    }
    while (h >= 1) {
        for (int i = h; i < length; i++) {
            for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
                std::swap(array[j], array[j - h]);
            }
        }
        h = h / 3;
    }
}

归并排序:

迭代版:

template<typename T> // 整數或浮点数皆可使用,若要使用物件(class)时必须设定"小于"(<)的运算子功能
void merge_sort(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;
}

递归版:

void Merge(vector<int> &Array, int front, int mid, int end) {
    // preconditions:
    // Array[front...mid] is sorted
    // Array[mid+1 ... end] is sorted
    // Copy Array[front ... mid] to LeftSubArray
    // Copy Array[mid+1 ... end] to RightSubArray
    vector<int> LeftSubArray(Array.begin() + front, Array.begin() + mid + 1);
    vector<int> RightSubArray(Array.begin() + mid + 1, Array.begin() + end + 1);
    int idxLeft = 0, idxRight = 0;
    LeftSubArray.insert(LeftSubArray.end(), numeric_limits<int>::max());
    RightSubArray.insert(RightSubArray.end(), numeric_limits<int>::max());
    // Pick min of LeftSubArray[idxLeft] and RightSubArray[idxRight], and put into Array[i]
    for (int i = front; i <= end; i++) {
        if (LeftSubArray[idxLeft] < RightSubArray[idxRight]) {
            Array[i] = LeftSubArray[idxLeft];
            idxLeft++;
        } else {
            Array[i] = RightSubArray[idxRight];
            idxRight++;
        }
    }
}

void MergeSort(vector<int> &Array, int front, int end) {
    if (front >= end)
        return;
    int mid = (front + end) / 2;
    MergeSort(Array, front, mid);
    MergeSort(Array, mid + 1, end);
    Merge(Array, front, mid, end);
}

堆排序:

#include <iostream>
#include <algorithm>
using namespace std;

void max_heapify(int arr[], int start, int end) {
    // 建立父节点指标和子节点指标
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { // 若子节点指标在范围内才做比较
        if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比较两个字节点大小,选择最大的
            son++;
        if (arr[dad] > arr[son]) // 如果父节点大于子节点代表调整完毕,直接跳出函数
            return;
        else { // 否则交换父子內容再继续将子节点和孙节点比较
            swap(arr[dad], arr[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}

void heap_sort(int arr[], int len) {
    // 初始化,i从最后一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; i--)
        max_heapify(arr, i, len - 1);
    // 先將第一个元素和已经排好的元素前一位做交换,再重新调整(刚调整的元素之前的元素),直到排序完毕
    for (int i = len - 1; i > 0; i--) {
        swap(arr[0], arr[i]);
        max_heapify(arr, 0, i - 1);
    }
}

int main() {
    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    heap_sort(arr, len);
    for (int i = 0; i < len; i++)
        cout << arr[i] << ' ';
    cout << endl;
    return 0;
}

桶排序:

元素分布在桶中:

然后,元素在每个桶中排序:

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

基数排序:

int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int maxData = data[0];              ///< 最大数
    /// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
    for (int i = 1; i < n; ++i)
    {
        if (maxData < data[i])
            maxData = data[i];
    }
    int d = 1;
    int p = 10;
    while (maxData >= p)
    {
        //p *= 10; // Maybe overflow
        maxData /= 10;
        ++d;
    }
    return d;
/*    int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n; ++i)
    {
        while(data[i] >= p)
        {
            p *= 10;
            ++d;
        }
    }
    return d;*/
}
void radixsort(int data[], int n) //基数排序
{
    int d = maxbit(data, n);
    int *tmp = new int[n];
    int *count = new int[10]; //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) //进行d次排序
    {
        for(j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空计数器
        for(j = 0; j < n; j++)
        {
            k = (data[j] / radix) % 10; //统计每个桶中的记录数
            count[k]++;
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++) //将临时数组的内容复制到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    delete []tmp;
    delete []count;
}

相关推荐:

1.0 十大经典排序算法 | 菜鸟教程 (runoob.com)https://www.runoob.com/w3cnote/ten-sorting-algorithm.html

首页 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/

动画阐释各种排序算法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV13Y4y1H7j5

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亖嘁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值