2024年最新2(1),阿里P8C C++架构师谈

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2.选择排序

**首先i****等于0,**每次i++,并从i轮询到末尾,选择一个最小者与第i个位置进行交换.

比如:

16,8,21,10,49

第1次遍历整个数组,找到最小值8,则与arr[0]进行交换:

8,16,21,10,49

第2次遍历下标1~4的数组,找到10,则与arr[1]进行交换:

8,10 ,21,16,49

第3次遍历下标2~4的数组,找到16,则与arr[2]进行交换:

8,10 , 16, 21,49

第4次遍历下标3~4的数组,找到21,由于交换的位置相等,则保持不变

由于第5次,起始小标等于n-1了.所以已经比较完了.则结束了.

所以代码如下所示:

template <typename T>
void mySwap(T& a, T& b)    // 交换函数
{
    T c(a);
    a = b;
    b = c;
}


template <typename T>
void seleteSort(T arr[], int len, bool ascend = true)      // ascend为ture表示升序
{
    for (int i = 0; i < len -1; ++i) {
        int minIdx = i;
        for (int j = i+1; j < len; ++j) {
            if (ascend ? (arr[minIdx] > arr[j]) : (arr[minIdx] < arr[j])) {
                minIdx = j;
            }
        }
        if (minIdx != i) {
            mySwap(arr[i], arr[minIdx]);
        }
    }
}

测试代码如下所示:

    int arr[8] = {25, 22, 12, 8, 9, 11, 30 ,40};

    bubbleSort(arr, 8);
    cout<<"ascend: "<<endl;
    for (int i = 0; i < 8; ++i) {
        cout<<i<<": "<<arr[i]<<endl;
    }

    bubbleSort(arr, 8, false);
    cout<<"descend: "<<endl;
    for (int i = 0; i < 8; ++i) {
        cout<<i<<": "<<arr[i]<<endl;
    }

打印如下所示:

总结:

选择排序是不稳定的排序算法,例如 **[3, 4, 3, 1, 5]**这个数组,第一次交换,第一个3和1交换位置,此时原来两个3的相对位置发生了变化,所以无法保证值相等的元素的相对位置不变,

3.冒泡排序

重复len次冒泡,每次冒泡都是**(int j=len-1; j>i; j–)从数组末尾往前进行冒泡,如果arr[j-1]>arr[j],则将arr[j]与arr[j-1]**交换,让值小的冒泡上去.

代码如下所示:

template < typename T >
static void bubbleSort(T arr[], int len, bool ascend = true)
{
    bool isSwap = true;

    for(int i=0; (i<len) && isSwap; i++)    // 每次冒泡时,则判断上次是否发生过交换,如果交换过,那说明还不是个有序的表
    {
        isSwap = false;     // 每次冒泡的时候复位 “交换标志位”

        for(int j=len-1; j>i; j--)
        {
            if( ascend ? ( arr[j-1] > arr[j] ) : (arr[j-1] < arr[j] ) ) // 如果是升序,arr[j-1] > arr[j],则将arr[j]从末尾冒泡冒上去
            {
                mySwap(arr[j], arr[j-1]);
                isSwap = true;     // “交换标志位” 设置为true
            }
        }
    }
}

PS: 由于mySwap()函数和测试代码已经写过了,后面就不再重复写了。

总结:

冒泡排序是稳定的排序算法,因为每次都是冒泡相邻比较,比如升序,如果后者>=前者,是不会进行交换

4.插入排序

将一个数组分为两个部分,左边是排序好的,右边是未排序的.

然后每次提取一个右边的数据出来,然后轮询左边(排序好的),如果找到合适的位置(前者小于它且后者大于它),则插入进去.如果未找到,则插入在左边排序好的末尾位置.

比如16,8,21,10,49,由于左边默认会有一个数值(一个数值无需判断比较),所以无需判断arr[0]:

**16  |  8,21,10,49  ( |****左边是排序好的,**右边是等待排序的 )

**第1****次,****获取arr[1],由于8小于16,插入在16前面,**所以插入后:

8,16  |  21,10,49

**第2****次,****获取arr[2],****向前轮询,****由于21>16,**所以停止向前遍历, **并且位置没改变过,**所以无需操作:

8,16,21  |  10,49

**第3****次,**获取arr[3], **向前轮询,****由于10<21,则21向后挪位,****再继续向前轮询,****由于10<16,则16向后挪位,**最后10>=8,则插入在8后面:

8, 10,16,21  |  49

**第4****次,****获取arr[4],****由于49>21,**所以停止向前遍历, 并且位置没改变过,所以无需操作最终为:

8, 10,16,21 ,49

代码如下所示:

template < typename T >
static void insertSort(T arr[], int len, bool ascend = true)
{
    for(int i=1; i<len; i++) // 循环取出右边未排序的
    {
        int k = i;
        T temp = arr[i];		// 把值取出来,后面会进行挪位操作,会覆盖掉arr[i]原来的内容

        // 如果ascend为true,则表示升序,那么当后者大于前者时,则停止for轮询,因为左边是有序序列
        for(int j=i-1; (j>=0) && (ascend ? (arr[j]>temp) : (arr[j]<temp)); j--)    
        {
            arr[j+1] = arr[j];   // 进行先后挪位操作
            k = j;				 // 更新要插入的位置
        }

        if( k != i )			// 如果未进行挪位,那么k==i,则不需要重复插入
        {
            arr[k] = temp;
        }
    }
}

总结:

插入排序是稳定的排序算法,例如 [4,3, 3, 1, 5]这个数组,由于左边的3是提前插入的[ 3, 4 | 3, 1, 5**]**,而后续的3由于>=前面的3,所以插入在后面

5.希尔排序

希尔排序是插入排序的升级版.并且比插入排序快.

希尔排序则是将一个插入排序,比如初始步长间隔gap为3,那么将会分成3个小组进行插入排序,每个小组插入排序好后,再次将步长间隔gap较少一部分再次进行插入排序,直到最后步长偏移为1后,进行整个插入排序.一般gap步长都是以 len/3+1来计算.以后每次以 gap/3+1来缩小。

PS: 也可以设置gap固定增量从 n/2 开始,以后每次缩小到原来的一半。

比如下图所示:

代码如下所示**😗*

template < typename T >
static void shellSort(T arr[], int len, bool ascend = true)
{
    int gap = len;

    while (gap > 1) {

        gap = gap / 3 + 1;      // 加一能够保证gap最后一次为1.


        for(int offset = 0 ; offset < gap; ++offset) {      // 对每组进行插入排序

            for(int i=gap-offset; i<len; i+=gap) // 循环取出右边未排序的
            {
                int k = i;
                T temp = arr[i];		// 把值取出来,后面会进行挪位操作,会覆盖掉arr[i]原来的内容
                // 假如ascend为true,则表示升序,那么当后者大于前者时,则停止for轮询
                for(int j=i-gap; (j>=0) && (ascend ? (arr[j]>temp) : (arr[j]<temp)); j-=gap)     
                {
                    arr[j+gap] = arr[j];   // 进行先后挪位操作
                    k = j;				 // 更新要插入的位置
                }

                if( k != i )			// 如果未进行挪位,那么k==i,则不需要重复插入
                {
                    arr[k] = temp;
                }
            }

        }
    }
}

总结:

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

g-cj9wRzXq-1715620319396)]
[外链图片转存中…(img-sIPCfN0M-1715620319397)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值