查找排序算法描述+源码


源码在文章最后面

用于看文字描述后容易写出相对应的查找排序算法代码

1.基数排序

本质上是对一个数(例如5400)的每一位都进行排序
①所需要的n个队列,n是所有数字的范围
123,456,789,158
这四组数包含了9个数字,所以需要9个队列

②然后按升序或者降序依次入队,然后出队
即排列了一次,最高位是m位,则排m次。

2.选择排序 【0号位为哨兵】

核心思想是找到无序集合中的最小值的下标,然后与无序集合中的第一个位置进行一次交换。
因为没找到一次都要进行一次交换 ,所以只需要找n-1次即可。

①外层循环是枚举n-1次

②内层循环是[i,n),寻找最小值下标

③交换

3.冒泡 疯狂交换排序

建立一个flag 一旦一轮比较都没有进行交换 说明 已经有序
这个操作影响最优时间复杂度

①和选择排序一样外层只要n-1次

②[0,j-i) 飘上去 每i轮后面少i个元素

4.直接插入排序

有序和无序的部分的思想比其他的排序更为直接。
一开始就是认为1号元素,因为只有一个元素,所以这1个元素是有序的,然后把后面的无序部分的元素一个一个的插入到有序的部分,这里的插入过程是从后面开始不断的覆盖的过程,直到找到位置,然后将a[0]插入。
简单来说就是有条件的覆盖,不是已知位置的覆盖
,边寻找位置 边覆盖。

①因为1视为有序部分,所以外层从2开始 [2,n)

②j=i为上界 当 目标元素a[0] < or > a[j-1] 时覆盖(因为i是目标元素,所以j也是目标元素,所以从j-1开始比较)

③当内层循环结束时会走到前一个位置,所以j+1赋值为a[0]

5.二分插入排序

与直接插入有着大概一半的不同。
这个的覆盖是已知的,因为使用了二分法找到了需要插入的位置,然后才开始进行覆盖操作。

①第一个循环依旧是 从2开始 [2,N)

②二分法寻找插入位置(因为每一个元素都要寻找位置所以放在最外层循环里面)

我们所需要插入的地方是有序表,
所以 l=1 h=i-1
有序表在左边 low理所当然为0,h则是上界,上界则是i-1,因为i是目标元素的下标。

此外二分法的其他部分不需要改变
结束的时候可以使用h+1作为插入点 因为h在结束的时候【这一段不是很好解释 自己体会把】
③h+1当作是插入点 所以开始覆盖操作 然后插入完事

6.快速排序

「我感觉更适合叫做pivot中心(中间枢纽)排序」 【 传的是low 和hight 存在两个数就是 low<hight】
①当存在两个数以上,获取一个区间,找到key的pivot,递归 pivot 的 左区间 和 右区间
②寻找pivot ,【默认key为low下标】
先保存key
找hight-- 比pivot小 放置low下标
找low 同理 放置hight下标
此时low空了,最后把pivot放置low位置
返回pivot位置 也就是 low

7.归并排序 与快排做对比叙述

开始时刻:
快排:递归开始时------就开始一个一个的找pivot,再分区间,从第一个元素就开始
归并:回溯时才开始

设计方式:
先开辟一个相同的集合,复制一份为t,再把t分为两个部分, 然后按照 合并规则 插入 原集合。

合并规则:
设置三个变量, i.j.k, i控制前半部分,j控制后半部分,k控制将要插入的集合
然后 是跟合并有序表的操作类似。
(写变量的下表的时候最好不用-(减), 容易造成负数)
注意:(写游标移动的时候一定要记得加上 原游标的范围条件判断)

本人手撸源码合集。顺序.二分查找+简单选择排序+堆排序+冒泡排序+快速排序+直接插入排序+二分插入排序+希尔排序+归并排序

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

/*
顺序查找
二分查找
基数排序
选择排序
冒泡
直接插入
二分插入
希尔排序
堆排序
快排
2路归并
*/

int a[11] = { 0,14,9,6,13,21,10,16,17,2,12 };

//int a[5] = {0,1,5,6,8};

//顺序查找
//return 0 查找失败   
int ss(int key, int length) {
    a[0] = key;
    int i;
    for (i = length; key != a[i]; i--);
    return i;
}

//二分查找
int b_s(int key, int length) {
    int l = 1, m, h = length;
    while (l <= h) {
        m = (l + h) / 2;
        if (a[m] == key) {
            return m;
        }
        else if (key < a[m]) {
            h = m - 1;
        }
        else if (key > a[m]) {
            l = m + 1;
        }
    }
    return 0;
}

//基数  可分   数字范围 n  开辟n个队列       数字的位数m   依次顺序入队出队m次

//*******************************************
//希尔排序
//实际个数
void shell(int n){
	//公差>=1
	for(int dk=n/2;dk>=1;dk/=2){
		//从各组的无序集的首位开始,一组一个
		for(int i=1+dk;i<=n;i++){
			a[0]=a[i];
			//有序集最后一个与key不符合要求
			if(a[i-dk]<a[0]){
				int j;
				//循环的终止条件两个,j>0必然,一旦不符合直接中断,这样才是前移dk,
											//若不是并列,永远移动到最前端
				for(j=i-dk;j>0 && a[j]<a[0];j-=dk){
					a[j+dk]=a[j];
				}
				//前移了dk
				a[j+dk]=a[0];
			}
		}
	}
}
void swap(int* a, int* b) {
    int* t = a;
    a = b;
    b = t;
}

//调整堆
void adjust_heap(int key, int length) {
    a[0] = a[key];
    for (int i = key * 2; i <= length; i *= 2)
    {
        if (i < length && a[i] < a[i + 1])
        {
            i++;
        }
        if (a[0] >= a[i])
        {
            break;
        }
        else {
            a[key] = a[i];
            key = i;
        }
    }
    a[key] = a[0];
}

//建堆
void build_heap(int length) {
    for (int i = length / 2; i > 0; i--)
    {
        adjust_heap(i, length);
    }
}

//堆排序
void heap_sort(int length) {
    build_heap(length);
    for (int i = length; i > 0; i--)
    {
        swap(a[1], a[i]);
        adjust_heap(1, i - 1);
    }
}

//选择排序
void select_sort(int length) {
    for (int i = 1; i < length; i++) {
        a[0] = a[i];
        int minarr = i;
        for (int j = i; j <= length; j++)
        {
            if (a[j] < a[0])
            {
                minarr = j;
                a[0] = a[j];
            }
        }
        swap(a[i], a[minarr]);
    }
}


//冒泡排序
void bubble_sort(int length) {
    for (int i = 1; i < length; i++)
    {
        bool flag = 1;
        for (int j = 1; j <= length - i; j++)
        {
            if (a[j] < a[j + 1])
            {
                swap(a[j], a[j + 1]);
                flag = 0;
            }
        }
        if (flag)    break;
    }
}

//pivot
int portion(int l, int h) {
    a[0] = a[l];
    while (l < h)
    {
        while (l < h && a[h] >= a[0])  h--;
        a[l] = a[h];
        while (l < h && a[l] <= a[0])  l++;
        a[h] = a[l];
    }
    a[h] = a[0];
    return h;
}

//快排
void quick_sort(int l, int length) {
    if (l < length) {
        int pivot = portion(l, length);
        quick_sort(l, pivot - 1);
        quick_sort(pivot + 1, length);
    }
}

//二分插入排序
void b_insert_sort(int length)
{
    //1位置认为有序
    for (int i = 2; i <= length; i++)
    {
        a[0] = a[i];
        //对于每一个都使用二分法找到位置
        int l = 1, m, h = i - 1;

        while (l <= h)
        {
            m = (l + h) / 2;
            if (a[0] < a[m]) {
                h = m - 1;
            }
            else {
                l = m + 1;
            }
        }
        //位置为h+1  覆盖
        for (int j = i; j > h + 1; j--)
        {
            a[j] = a[j - 1];
        }
        a[h + 1] = a[0];
    }
}

//归并操作
void my_merge(int l, int h, int length) {
    int* b = (int*)malloc(sizeof(int) * length);
    for (int i = 1; i <= length; i++)
    {
        b[i] = a[i];
    }
    int m = (l + h) / 2;
    int i, j, k;
    for (i = l, j = m + 1, k = l; i <= m && j <= h; k++)
    {
        if (b[i] < b[j]) {
            a[k] = b[i++];
        }
        else {
            a[k] = b[j++];
        }
    }
    while (i <= m)
    {
        a[k++] = b[i++];
    }
    while (j <= h)
    {
        a[k] = b[j++];
    }
}

//归并排序
void merge_sort(int l, int h, int length) {
    if (l < h) {
        int m = (l + h) / 2;
        merge_sort(l, m, length);
        merge_sort(m + 1, h, length);
        my_merge(l, h, length);
    }
}

//int a[5] = { 10,6,2,8,1 }

int main()
{
    bubble_sort(10);
    for (int i = 1; i < 11; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}



求点赞👍👍👍
原创不易,点赞容易。
您的鼓励就是我的最大动力!!!。

本篇博客到此结束,谢谢大家观看。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值