2024年C C++最新2,神操作

img
img

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

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

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

}

}


测试代码如下所示:



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

打印如下所示:


![](https://img-blog.csdnimg.cn/08fa12d515e9453bac65dc84db5bd7d4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6K-66LCm,size_15,color_FFFFFF,t_70,g_se,x_16)


**总结:**


选择排序是不稳定的排序算法,例如 **[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 开始,以后每次缩小到原来的一半。**


**比如下图所示:**


![](https://img-blog.csdnimg.cn/c729e29a1d2f41c9951040ec5f0c3e30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6K-66LCm,size_20,color_FFFFFF,t_70,g_se,x_16)


**代码如下所示****:**



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

    }
}

}


**总结:**


希尔排序是不稳定的排序算法,因为希尔排序通过分组方法,可能会将最后的值跳过中间重复的值排序到前面



## **6.归并排序**


归并是将两个或多个有序序列合并成一个新的有序序列。归并方法有多种,一次对两个有序记录序列进行归并,称为**二路归并排序**,也有**三路归并排序**及**多路归并排序**。本代码是**二路归并排序**.


**思路如下所示:**


通过递归的方式将一个无序序列,对半拆解、直到不能拆解时,则进行两路比较排序(归并)到一个辅助空间数组中,归并完成后则将辅助数组中内容拷贝回去,返回上一级递归再进行两路比较排序(归并)和拷贝.直到最后则整个序列归并完成.


**如下图所示(红色数字表示递归拆解和归并的先后顺序):**


![](https://img-blog.csdnimg.cn/f962265eaffb49b48f1a90c20819c959.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6K-66LCm,size_20,color_FFFFFF,t_70,g_se,x_16)


 代码如下所示:



template < typename T >
static void merge(T arr[], int l, int mid, int r, bool ascend = true) // 进行比较归并
{
int n = r - l + 1;
T* helper = new T[n]; // 创建一个辅助空间,用来临时存储

int i = 0;
int left = l;
int right = mid+1;
while (left <= mid && right <= r) {
    // 如果ascend = true, 则判断左边如果大于右边的,则存放右边的
    if (ascend ? arr[left] > arr[right] : arr[left] < arr[right])
        helper[i++] = arr[right++];
    else
        helper[i++] = arr[left++];
}

// 将某一侧剩余的存放进去
while (left <= mid)
     helper[i++] = arr[left++];

while (right <= r)
     helper[i++] = arr[right++];


// 最后将排序好的替换到原数组
for (i = 0; i < n; ++i) {
    arr[l + i] = helper[i];
}

delete [] helper;

}

template < typename T >
static void mergeSort(T arr[], int l, int r, bool ascend = true) // 递归拆解
{
if (l >= r) // 不能再进行拆解了,直接退出
return;

int mid = (l+r)/2;

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

(l+r)/2;

[外链图片转存中…(img-2an5SLWS-1715544750615)]
[外链图片转存中…(img-qBUQ3G1i-1715544750616)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值