有关查找排序的一些算法

算法

  • 数据结构中的算法,指的是数据结构所具备的功能
  • 解决特定问题的方法,他是前辈们的优秀经验总结。

分治

  • 把一个大而复杂的问题,分解为很多个小的而简单的问题,利用计算机的强大计算能力来解决问题。
  • 实现的方法
    1. 循环、递归
      • 递归:函数自己调用自己的一种行为,可以形成循环调用,进而实现分治算法

      • 使用递归的情况:

        1. 问题过于复杂,无法拆解为循环
        2. 问题是非线性的,函数的每一次调用都会重新将数据压入栈空间,数据会保留。因此可以实现非线性的问题.在单线程模式下只能同时执行一个函数,当函数自己调用自己时(子级),会先执行子级,完事后返回上级继续执行
      • 如何安全的实现递归

        • 使用递归非常有可能造成"死循环",非常浪费资源。
        1. 先设置一个出口
          • if(…) return …;
        2. 解决一个小问题
        3. 剩下的问题交给下一级
    2. 优点
      • 代码简单、容易理解
    3. 缺点
      • 比较耗费内存,且浪费时间

查找

  1. 顺序查找
    • 从头到尾逐一比较 对数据没有要求,方法简单,效率低
  2. 二分查找
    • 数据有序,从数据的中间位置开始查,
  3. 块查找、权重查找
    • 适用于特殊条件下,需要对数据排序、分析、总结、归纳。

排序

  • 稳定性:表中有相同的值时,算法会交换位置吗。
  1. 冒泡:

    • 稳定排序 可以在排序时检测到数据是否已经有序,可以立即停止。如果无序的数据基本有序,则冒泡的效率很高
    void bubble(int* arr,size_t len)
    {
        for(int i=len-1;i>0;i--)
        {
            bool flag = true;
            for(int j=0;j<i;j++)
            {
                if(arr[j] > arr[j+1])
                {
                    swap(arr[j],arr[j+1]);
                    flag = false;
                }
                if(flag) break;
            }
        }
    }
    
  2. 插入排序:

    • 当一列数已经有序,再有新加入的数时,时候使用插入排序
    void cr(int* arr,size_t len)
    {
    
        for(int i=1; i<len; i++)
        {
            int a = arr[i],k = i;
            for(int j=i-1;j>=0 && arr[j] > a;j--)
            {
                    arr[j+1] = arr[j];
                    k = j;
            }
            arr[k] = a;
        }
    }
    
  3. 选择排序:

    • 先记录当前下标,对比完后下标内容互换。这是冒泡排序的一种变种,但没有冒泡对数据的敏感。排序时少了许多数据交换(数据比较混乱时比冒泡快)
    void select_sort(int* arr,size_t len)
    {
        for(int i=0;i<len-1;i++)
        {
            int index = i;
            for(int j=i+1;j<len;j++)
            {
                if(arr[j] < arr[index])
                    index = j;
            }
            if(index != i)
            {
                swap(arr[index],arr[i]);
            }
        }
    }
    
  4. 快速排序:

    • 一种基于交换的排序
    void _quick(int* arr,size_t l,size_t r)
    {
        if(l >= r) return;
        //计算标杆下标
        int pi = (l + r)/2;
        //备份标杆值
        int pv = arr[pi];
        //备份左右下标
        int left = l,right = r;
        //不超出范围
        while(left < right)
        {//在标杆左边寻找比标杆大的数
            while(arr[left] <= pv && l < pi) left++;
            if(left<pi)
            {//与标杆交换位置,并记录新的标杆位置
                arr[pi] = arr[left];
                pi = left;
            }
            //在标杆右边寻找比标杆大的数;
            while(pi < right && arr[right] >= pv) right--;
            if(pi < right)
            {
                arr[pi] = arr[right];
                pi = right;
            }
        }
        //还原标杆值
        arr[pi] = pv;
        if(pi-l>1) _quick(arr,l,pi-1);
        if(r-pi>1) _quick(arr,pi+1,r);
    
    }
    void quick(int* arr,size_t len)
    {
        _quick(arr,0,len-1);
    }
    
    
  5. 堆排序:

    • 先把待排序的数组当做完全二叉树,然后保障根结点最大,然后把根结点与最后一个元素交换,再调整二叉树,使根保持最大并且重复操作逐渐减少数组
    void creat_heap(int* arr,size_t len,size_t root)
    {
        if(root >= len) return;
        int left = root*2+1;
        int right = root*2+2;
        creat_heap(arr,len,left);
        creat_heap(arr,len,right);
        int max = root;
        if(left < len)
        {
            if(arr[left] > arr[max])
                max = left;
        }
        if(right < len)
        {
            if(arr[right] > arr[max])
                max = right;
        }
    
        if(max != root)
        {
            swap(arr[max],arr[root]);
        }
    
    }
    
    void heap(int* arr,size_t len)
    {
        for(int i=0;i<len;i++)
        {
            creat_heap(arr,len,0);
        }
    }
    
  6. 归并排序:

    • 不交换顺序,但需要借助额外的空间,用作临时存储空间
    //递归方法
    void _mergr(int* arr,size_t left,size_t right,int* temp)
    {
        if(left >= right) return;
        int pi = (left+right)/2;
        _mergr(arr,left,pi,temp);
        _mergr(arr,pi+1,right,temp);
        merge(arr,left,pi,right,temp);
    }
    void mergr(int* arr,size_t len)
    {
        int temp[10];
        _mergr(arr,0,len-1,temp);
    }
    
    //循环方法
    void merge(int* arr,size_t left,size_t pi,size_t right,int* temp)
    {
        int i = left,j = pi+1,k = left;
        while(i<=pi && j<=right)
        {
            if(arr[i] < arr[j])
                temp[k++] = arr[i++];
            else
                temp[k++] = arr[j++];
    
        }
        while(i<=pi) temp[k++] = arr[i++];
        while(j<=right) temp[k++] = arr[j++];
        for(int a=left;a<=right;a++)
        {
            arr[a] = temp[a];
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值