十大排序算法个人笔记

文章目录

排序算法基础:

排序是数据处理的基础,也是影响程序效率的重要组成因素。下面对常用的排序算法进行总结,并列举了面试中的遇到的部分问题:
理论基础:
博客园大牛笔记

个人代码实现:

#include <iostream>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

// 冒泡排序,从末尾逐一选择较小的元素存储到较前的位置,直至未排序的最前位置
void bubbleSort(vector<int> & source){
    for(int i = 0; i < source.size(); i++){
        for(int j = source.size()-1; j > i; j--){
            if(source[j-1] > source[j]){
                int tmp = source[j-1];
                source[j-1] = source[j];
                source[j] = tmp;
            }
        }
    }
    return;
}

// 插入排序(类似于打扑克,把后面的牌插入前面的牌中)
void Insertionsort(vector<int> & source)
{
    //将按升序排列
    int n=source.size();
    for (int i=1;i<n;i++)
    {
    //将a[i]插入到a[i-1],a[i-2],a[i-3]……之中
        for(int j=i;j>0&&source[j] < source[j-1];j--)
        {
            int temp    = source[j];
            source[j]   = source[j-1];
            source[j-1] = temp;
        }
    }
    return;
}

// 选择排序,每次选择最小/最大的交换存放到前面(无序)
void SelectionSort(vector<int> & source){
    for(int i = 0; i < source.size(); i++){
        int minnum = i;
        for(int j = i+1; j < source.size(); j++){
            if(source[minnum] > source[j]){
                minnum = j;
            }
            int tmp = source[i];
            source[i] = source[minnum];
            source[minnum] = tmp;
        }
    }
    return;
}

// 快速排序
void fastranknum(vector<int> & source, int left, int right){
    if(left>=right){
        return;
    }
    int mid = (left + right)/2;
    swap(source[mid], source[right]);
    int small = left -1;
    for(int i = left; i < right; i++){
        if(source[i] < source[right]){
            ++small;
            if(small != i) swap(source[small], source[i]);
        }
    }
    ++small;
    swap(source[small], source[right]);
    fastranknum(source, left, small);
    fastranknum(source, small+1, right);
    return;
}

// 归并排序
void remergeRanknum(vector<int> & source, int left, int right){
    if(left>=right){
        return;
    }
    int mid = (left + right)/2;
    remergeRanknum(source, left, mid);     // 归并左边
    remergeRanknum(source, mid+1, right);  // 归并右边
    vector<int> nums(right-left+1, 0);
    for(int index = left; index <= right; index++){
        nums[index-left] = source[index];
    }

    int i =left, j = mid+1;
    for(int index = left; index <= right; index++){
        if(i > mid){
            source[index] = nums[j-left];
            j++;
        }else if(j > right){
            source[index] = nums[i-left];
            i++;
        }else if(nums[i-left] < nums[j-left]){
            source[index] = nums[i-left];
            i++;
        }else{
            source[index] = nums[j-left];
            j++;
        }
    }
    return;
}

// 希尔排序
void shellSort(vector<int> & source) {
    int len = source.size();
    for (int gap = len / 2; gap > 0; gap = gap / 2) {
        // 注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行
        for (int i = gap; i < len; i++) {
            int j = i;
            int current = source[i];
            while (j - gap >= 0 && current < source[j - gap]) {
                 source[j] = source[j - gap];
                 j = j - gap;
            }
            source[j] = current;
        }
    }
    return;
}

// 堆排序子过程
void max_heapify(vector<int> &source, int start, int end) 
{
    //建立父节点指标和子节点指标
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end)  //若子节点指标在范围内才做比较
    {    
        if (son + 1 <= end && source[son] < source[son + 1]) //先比较两个子节点大小,选择最大的
            son++;
        if (source[dad] > source[son]) //如果父节点大於子节点代表调整完毕,直接跳出函数
            return;
        else  //否则交换父子内容再继续子节点和孙节点比较
        {
            swap(source[dad], source[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}
 
// 堆排序
void heap_sort(vector<int> & source) 
{
    int len = source.size();
    //初始化,i从最後一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; i--)
        max_heapify(source, i, len - 1);
    //先将第一个元素和已经排好的元素前一位做交换,再从新调整(刚调整的元素之前的元素),直到排序完毕
    for (int i = len - 1; i > 0; i--) 
    {
        swap(source[0], source[i]);
        max_heapify(source, 0, i - 1);
    }
}

// 计数排序 1)根据排序的最大和最小值之差,计算出计数区间;2)统计各个字段的值,然后遍历区间,把根据从小到大的顺序把数保存起来
void countSort(vector<int> & source){
    int vecMin = INT_MAX, vecMax = INT_MIN;
    for(int i = 0; i < source.size(); i++){
        source[i] < vecMin?vecMin = source[i]:vecMin;
        source[i] > vecMax?vecMax = source[i]:vecMax;
    }
    vector<int> keep(vecMax-vecMin+1,0);
    for(int i = 0; i < source.size(); i++){
        keep[source[i]-vecMin]++;
    }
    int j = 0;
    for(int i = 0; i < keep.size(); i++){
        while(keep[i]){
            source[j] = i+vecMin;
            j++;
            keep[i]--;
        }
    }
}

// 桶排序 在计数排序的基础上,进行了部分优化,缩短了统计区间,并用插入排序对小区间进行排序
void bucketSort(vector<int> & source, int bucketSize =10){ // source排序数组,bucketSize桶的大小
    int vecMin = INT_MAX, vecMax = INT_MIN;
    bucketSize = bucketSize;

    for(int i = 0; i < source.size(); i++){
        source[i] < vecMin?vecMin = source[i]:vecMin;
        source[i] > vecMax?vecMax = source[i]:vecMax;
    }

    int bucketCount = (vecMax - vecMin) / bucketSize + 1; 
    vector<vector<int>> keep(bucketCount);
    for(int i = 0; i < source.size(); i++){
        keep[(source[i]-vecMin)/bucketSize].push_back(source[i]);
    }

    int j = 0;
    for(int i = 0; i < keep.size(); i++){
        Insertionsort(keep[i]);
        for(int k = 0; k < keep[i].size(); k++){
            source[j] = keep[i][k];
            j++;
        }
    }
}

// 基数排序 从个位到最高位依次从0-9进行排序
void radixSort(vector<int> & source) {
    int vecMax = INT_MIN;
    vector<vector<int> > counter(10);

    for(int i = 0; i < source.size(); i++){
        source[i] > vecMax?vecMax = source[i]:vecMax;
    }
    int maxDigit = 0;
    int nCount = vecMax;
    while(nCount){
        maxDigit++;
        nCount = nCount/10;
    }

    int mod = 10;
    int dev = 1;
    for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { // 从个位到最高位
        for(int j = 0; j < source.size(); j++) { // 记录0-9位数的值
            int bucket = (source[j] % mod) / dev;
            counter[bucket].push_back(source[j]);
        }
        int pos = 0;
        for(int j = 0; j < counter.size(); j++) { 
          for(int k = 0; k < counter[j].size(); k++){
              source[pos++] = counter[j][k];
          }
          counter[j].clear();
        }
    }
    return;
}


int main(){
    vector<int> vec = {1,23,232,3131,1313,3131,3134,3131,4,13,31,41,313,3133,3131,67,41,78,69,48};
    cout<<"原数组: ";
    for(int i = 0; i < vec.size(); i++){
		cout<<vec[i]<<" ";
	}
    cout<<endl;
    string algorUsed;
    cin>>algorUsed;
    if(!strcmp(algorUsed.c_str(), "bubble")){        // 冒泡排序
    	bubbleSort(vec);
    }else if(!strcmp(algorUsed.c_str(), "insert")){  // 插入排序
    	Insertionsort(vec);
    }else if(!strcmp(algorUsed.c_str(), "select")){  // 选择排序
    	SelectionSort(vec);
    }else if(!strcmp(algorUsed.c_str(), "fast")){    // 快速排序
    	fastranknum(vec, 0, vec.size());
    }else if(!strcmp(algorUsed.c_str(), "remerge")){ // 归并排序
    	remergeRanknum(vec, 0, vec.size());
    }else if(!strcmp(algorUsed.c_str(), "shell")){   // 希尔排序
    	shellSort(vec);
    }else if(!strcmp(algorUsed.c_str(), "heap")){    // 堆排序
    	heap_sort(vec);
    }else if(!strcmp(algorUsed.c_str(), "count")){   // 计数排序
    	countSort(vec);
    }else if(!strcmp(algorUsed.c_str(), "bucket")){  // 桶排序
    	bucketSort(vec);
    }else if(!strcmp(algorUsed.c_str(), "radix")){   // 基数排序
    	radixSort(vec);
    }else{
        cout<<"没有输入合适的算法,该数组暂未排序";
    }
    
    for(int i = 0; i < vec.size(); i++){
		cout<<vec[i]<<" ";
	}
    system("pause");
    return 0;
}

STL的sort排序是怎么实现的:
sort采用快速排序+插入排序+堆排序的方法来实现的,首先采用快速排序把数组分段,当数据量到达某个阈值(16)时,采用插入排序来减少继续分割带来的过大开销,为避免递归层次过深,还会用到堆排序来优化。
stl的实现原理介绍

扩展题:
一个数组:source = [2,0,3,12,0],target = [2,3,12,0,0]。实现把数组在原来位置相对不变的情况下,把0移至最后。

思路:采用插入排序,从末尾遍历数组,遇到0,则把它插入到最后一个非0的位置。
#inculde<iostream>
using namespace std;
int main(){
	vector<int> target = {2,0,3,12,0};
	int count = target.size()-1;
	for(int i = target.size()-1; i >= 0; i--){
		if(target[i] == 0 && i != target.size()-1){
			for(int j = i; j <= count; j++){
				target[j] = target[j+1];
			}
			target[count] = 0;
			count--;
		}
	}
	for(int i = 0; i < target.size(); i++){
		cout<<target[i]<<" ";
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值