左神算法课程基础笔记-第一章-认识时间复杂度以及排序算法

本文详细介绍了异或在数组元素交换中的应用,以及冒泡排序、选择排序和直接插入排序的原理和时间复杂度。通过实例解析了如何利用异或找到数组中奇数次出现的数,同时深入讲解了三种经典的排序算法的操作流程及其效率。

目录

1.异或在数组两元素交换中的妙用

2.冒泡排序 

3.选择排序

4.直接插入排序


1.异或在数组两元素交换中的妙用

eor存储着两个元素异或后的结果,异或:二进制运算中同一位如果相同则异或后为0,不相同则异或后为1。  a:1101,b:1001 异或后为 eor:0100 。 b=a^eor,a=b^eor。  

void swap(int arr[],int i,int j)
{
    //不能修改同一位置不让会使其异或为0
    if(i!=j) {
        int eor = arr[i] ^ arr[j];
        arr[i] = eor ^ arr[i];
        arr[j] = eor ^ arr[j];
    }
}

Example:找到数组中1个奇数次的数。 12323 

void find_1(int []arr)
{

    int eor=0;
    for (int i = 0; i < sizeof(arr)/sizeof(int); ++i)
    {
        eor^=arr[i];
    }
    cout<<"出现奇数次的数为:"<<eor<<endl;
}

Example:找到数组中2个奇数次的数。 12312313

rightone=eor&(~eor+1)得到一个数最有右侧的1

eor 是所有的数异或得到的结果是其中各位为1的代表的是在这组数出现奇数次的数,分别获取第一个最右侧的1让数组元素中和他位数与运算等于rightone的数即为两个中的其中一个得到aorb,然后通过eor1与eor(a^b)异或

//一组数中有两个数出现了奇数次得到这两个数
void  find_2(int arr[])
{
    int eor=0;
    for (int i = 0; i < sizeof(arr)/sizeof(int); ++i)
    {
        eor^=arr[i];
    }
    int rightone=eor&(~eor+1);//提取一个数的最右侧的1
    int eor1=0;
    for (int i = 0; i < sizeof(arr)/sizeof(int); ++i)
    {
        if ((arr[i]&rightone)==rightone)
        {
            eor1^=arr[i];  //获得a or b
        }
    }
    cout<<"第一个奇数次的数为:"<<(eor^eor1)<<endl;
    cout<<"第二个奇数次的数为"<<eor1<<endl;
    
}

2.冒泡排序 

冒泡排序一趟排序的过程,将相邻的两个元素进行比较,如果前一个比后一个大,则将两个元素交换将最大的元素交换到整个数据的最后。
排序的趟数:数据元素的个数:len - 1
void paoSort(int arr[],int length)
{
    for (int i = 0; i <length-1 ; ++i)
    {
        int flag=0;//标志位用来第一躺排序是否结束
        for (int j = 0; j <length-1-i ; ++j)
        {
            if (arr[j]>arr[j+1])
            {
                swap(arr[j+1],arr[j]);
                flag=1;
            }
        }
        if (flag==0) //一趟排序过后没有数据发生交换就说明数组已经有序,不用再进行排序,所以直接推出循环即可
        {
            break;
        }
    }
}

3.选择排序

时间复杂度:O(N^2)

算法流程:1.先遍历一遍整个待排序数据,找到当前最大的值的位置。 2.将标记的最大值与当前最后一个元素交换。 3.重复上述过程,直到只剩下一个数据 上面的步骤每做一次,下一次就少遍历一个数据。(本次找到的最大值) 选择排序执行的趟数:数据元素的个数 len - 1。flag作为减少迭代次数的标志位,如果第一轮一直位0则数组是有序,直接跳出循环。

void selectSort(int arr[],int length)
{
    int max_index=0; //查找最大值的过程
    for (int i = 0; i < length-1; ++i)
    {
        for (int j = 0; j < length-1-i; ++j)
        {
            if (arr[j]>arr[j+1])
            {
                max_index=j;
            }
        }
        swap(arr[max_index],arr[length-1-i]);// 交换最大值
    }
}

4.直接插入排序

平均时间复杂度:O(N^2)

算法流程:1.将数据分为两部分,前一段是已经有序的数据(初始时,前一段数据只有一个),后一段是无序数据。 2.从无序数据中拿一个数据(拿左边的第一个数据),插入到前一段的有序数据中,并且使其依旧有序。 3.重复上述过程,直到无序数据段没有数据。

void  inselectSort(int arr[],int length)
{
    for (int i = 0; i < length; ++i) //外层循环用来添加元素
    {
        //0-n-1所有元素
        int temp=arr[i]; //存储临时元素
        int j=0;
        for (int j = i-1; j >=0 ; j--)
        {
            if (arr[j]<temp)
            {
                break;
            }
            swap(arr[j],arr[j+1]);
        }

    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值