常见算法

那年仲夏 提交于 2020-02-16 18:38:43

【写在前面】

  • 这个是在巩固常见算法学习过程做的一些笔记,因为是笔记,所以后续先更新自己有道云普通笔记,再是md笔记,最后才是同步到博客园(即此地址)
  • 有道云普通链接
  • 有道云md地址


1. 冒泡排序

  • 思路:两两交换,较大的数值放后,第一次排序后最大已经在末尾
  • 算法动图•ᴗ•
  • 特点:需要n-1趟,比如10个数字,需要9次

代码实现要点:

  • 两个for循环,外层控制排序趟数,内层控制比较次数,因为每趟排序完成都会把最大的推到后面,所以每次趟数过后比较数都要减1
  • 优化:如果一次排序后没有交换位置那么该数组已经有序。
int[] list=new  int[]{1,4,3,2,9,7,8};
//事先申明免得每次换的时候都要实例化新的对象占用内存,设置参省防止没有循环导致的错误
int tem;
boolean isChange;

for(int i=0;i<list.length;i++)
{
  isChange=false;
  for(int j=0;j<list.length-1-i;j++)
  {
      if(list[j]>list[j+1])
      {
          tem=list[j];
          list[j]=list[j+1];
          list[j+1]=tem;
          isChange=true;
      }
  }

  //如果一趟下来没有排序,则说明已经排好了,不需要再执行后面排序
  if(isChange==false)
  {
      break;
  }
}

【补充】算法是否稳定判定方法:一个数组里相同的值,例如有两个4,结果经过排序之后,原来的第一个4排到了第二个4后面,那么就是不稳定的,反之则还是稳定的。

2. 快速排序

  • 思路:选定某个数字为基准数,将比基准数小的数字放到左边,大的数放到右边。

  • 算法动图•ᴗ•

  • 特点:是不稳定的

实现要点:指定最左和最右为L和R指针,如果选定的是左边第一个数字作为基准数

  • (步骤1)则从右边开始移动指针,如果有比基准数小的数,则将R指针与L指针所指的数交换。
  • (步骤2)第一次排序完成后,再从左边指针开始扫,如果有比基准数大的数,则将指针所指数交换。
  • 重复步骤1、2,直到L和R指针的位置重复,此时说明已经完成排序。
package cn.lxy;
public class Test {
   
  public static void main(String[] args) {
    int[] list = new int[] {5, 3, 8, 50, 6, 7, 20, 4, 9};
    for(int j:list)
    {
      System.out.print("-"+j+"-");
    }
    System.out.println();
    System.out.println("开始快速排序");
    getPartition(list,0,list.length-1);
   
    System.out.println("排序结果");
    for(int j:list)
    {
      System.out.print("-"+j+"-");
    }
   
  }
  //找到分割点并递归
  public static  void getPartition(int[] list, int left, int right)
  {
    if(left>=right)
    {
     return;
    }
   
    //存放临时变量
    int l,r,temp;
    l=left;
    r=right;
    //基准数
    int pivot=list[left];
    while (l<r)
    {
        //找到比基数小的数就交换,否则就一直移动下标。
        //这里的left小于right是因为后面的while可能会改变left和right的下标
       while(l<r&&list[r]>pivot)
        {
            r--;
        }
       
       
        //比基准数小的话就继续移动下标
        while (l<r&&list[l]<pivot)
        {
            l++;
        }
       
        if (l<r)
        {
          temp=list[l];
          list[l]=list[r];
          list[r]=temp;       
        } 
       
        System.out.println("(l:"+l+",r:"+r+")");    
    }
   
    list[l]=pivot;
    System.out.println("---基准点:list["+left+"]="+pivot+"---\n排序过程:");
    for (int j:list)
    {
      System.out.print("-"+j+"-");
    }
    System.out.println();
    getPartition(list,left,r-1);
    getPartition(list,r+1,right);
    
  }
 
 
}

3. 选择排序

  • 思路原理:找出等待排序的数组里最小(最大)的数,与待排序最前(最后)的数字替换,然后逐次将未排序完的循环排序,就能得到正确的数组顺序。
  • 算法动图•ᴗ•
  • 特点:不稳定
int[] list=new  int[]{1,4,3,2,5,10,6,9,7,8};
//事先申明免得每次换的时候都要实例化新的对象占用内存,设置参省防止没有循环导致的错误
//存放临时变量和下标
int tem,pos;

for(int i=0;i<list.length-1;i++)
{
    pos=i;
    for(int j=i+1;j<list.length;j++)
    {
        if(list[i]>list[j])
        {
            pos=j;
            tem=list[i];
            list[i]=list[pos];
            list[pos]=tem;
        }
    }

    for (int a:list)
    {
        System.out.print(a+",");
    }
    System.out.println();
}

【补充】 三大经典排序可参考链接>> 含算法动图 <<

4. 插入排序

  • 思路原理:将一个数据插入到已经排好序的有序数组,从而得到一个新的、个数加1的有序数组。其实就是将前面的数组慢慢排成有序的数组(第一个默认是有序的,第二个要和第一对比排序,以此类推),每次将还没排序的数插入到前面的有序数组中,最终的到一个有序的数组。
  • 特点:稳定,趟数也是n-1,时间复杂度为O(N^2),适用于少量数据的排序。
public class test {
    public static void main(String[] args) {
        int[] list=new int[]{8,1,9,4,6,4,9,3};
        //临时变量j是为了防止改变外层循环的i
        int j,tem;
        //这里默认第一个数是排列好的数组,所以直接对第二个开始排序
        for(int i=1;i<list.length;i++)
        {
            j=i;
            tem=list[i];
            //如插入数比所有数都小,会再找下标为-1的数,应限制比较到第一个数为止
            while(j>=1&&list[j-1]>tem)
            {
                list[j]=list[j-1];
                j--;
            }
            list[j]=tem;
            //测试
            for(int a:list)
            {
                System.out.print("-"+a+"-");
            }
            System.out.println();
        }
    }
}

5. 插入排序

to be done

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!