基础排序算法

一,选择排序

1,思想

不断的找到数组中最小的元素,往数组前面放。(找第1小的元素放到位置1,找第2小的元素放到位置2,…,第n小的元素放到位置n)

2,图解

在这里插入图片描述

3,实现

	  /**
		* 选择排序
		* @param arr
		*/
		public static void sort(int[] arr){
		   if(null == arr || arr.length <= 1){
		       return;
		   }
		   for(int i = 1; i < arr.length; i++){
		       int min = arr[i - 1], minIndex = i - 1;
		       //  找到最小的元素
		       for(int j = i; j < arr.length; j++){
		           if(arr[j] < min){
		               min = arr[j];
		               minIndex = j;
		           }
		       }
		       swap(arr, minIndex,i - 1);
		   }
		}
		
		/**
		 * 交换元素
		*/
		public static void swap(int[] arr,int a,int b){
		   int tmp = arr[a];
		   arr[a] = arr[b];
		   arr[b] = tmp;
		}

二,堆排序-大根堆

1,思想

不断的拿大根堆的根节点,结果就是一个降序排序
可以知道,我们通过二叉树的层序遍历给每个节点做个标记,标记为0~n,那么节点x(0<=x<=n)的父亲节点就是(x-1)/2向下取整的值

节点上升:每个节点的值都小于它的父亲节点。所以只要不断的判断当前节点和父亲节点,就可以构建大根堆。(父亲和爷爷也要判断

节点下降:把根节点取出来,把最后一个节点充当根节点,重新构造大根堆

2,图解

在这里插入图片描述

3,实现

  /**
	* 创建大根堆
	* @param arr
	*/
	public static void createMaxHeap(int[] arr){
	   if(arr.length <= 1){
	       return;
	   }
	   int i = 0;
	   //  每个节点都要判断是否满足:小于父亲节点
	   while(i < arr.length){
	       int currentIndex = i;
	       int fatherIndex = (currentIndex-1)/2;
	       //  不断判断,自己->父亲->爷爷->太爷爷... 两两之间是否满足
	       while(fatherIndex < arr.length && fatherIndex >= 0 && arr[currentIndex] > arr[fatherIndex]){
	           swap(arr,currentIndex,fatherIndex);
	           currentIndex = fatherIndex;
	           fatherIndex = (fatherIndex-1)/2;
	       }
	       System.out.println(Arrays.toString(arr));
	       ++i;
	   }
	}
	
	/**
	* 获得根
	* @param arr
	*/
	public static int[] getRoot(int[] arr){
	   //  获得根节点
	   System.out.println(arr[0]);
	   //  最后一个节点充当根节点
	   swap(arr,0,arr.length-1);
	   int[] ints = Arrays.copyOf(arr, arr.length - 1);
	   //  重构大根堆
	   createMaxHeap(ints);
	   return ints;
	}
	
	/**
	* 交换元素
	*/
	private static void swap(int[] arr,int a,int b){
	   int tmp = arr[a];
	   arr[a] = arr[b];
	   arr[b] = tmp;
	}

三,插入排序

1,思想

把一个数插入到已经排好序的数组中

2,图解

3,实现

/**
  * 插入排序
  * @param arr
  */
 public static void sort(int[] arr){
     for(int i = 1; i < arr.length; i++){
         int j = i;
         //  逐一和有序的元素比较和交换,最终找到自己的位置
         while(j >= 1 && arr[j] < arr[j-1]){
             swap(arr,j,j-1);
             j -= 1;
         }
     }
 }

 /**
  * 交换元素
  */
 private static void swap(int[] arr,int a,int b){
     int tmp = arr[a];
     arr[a] = arr[b];
     arr[b] = tmp;
 }

四,希尔排序

1,思想

在插入排序的基础上,把原来的步子迈大一点

2,图解

3,实现

   /**
     * 希尔排序
     * @param arr
     */
    public static void sort(int[] arr){
        if(null == arr || arr.length <= 1){
            return;
        }
        int step = arr.length/2;
        while(step != 0){
            realSort(arr,step);
            step /= 2;
        }
    }

    /**
     * 插入排序
     * @param arr
     * @param step
     */
    private static void realSort(int[] arr,int step){
        for(int i = step; i < arr.length; i += step){
            int j = i;
            while(j >= step && arr[j] < arr[j - step]){
                swap(arr,j,j - step);
                j -= step;
            }
        }
    }

    /**
     * 交换元素
     */
    private static void swap(int[] arr,int a,int b){
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }

五,冒泡排序

1,思想

两两相邻元素大的往后走

2,图解

3,实现

/**
     * 冒泡排序
     * @param arr
     */
    public static void sort(int[] arr){
        for(int i=1; i<arr.length; i++){
            for(int j=1; j<arr.length-i; j++){
                //  大的往后走
                if(arr[j-1]>arr[j]){
                    swap(arr,j,j-1);
                }
            }
        }
    }

    /**
     * 交换元素
     */
    private static void swap(int[] arr,int a,int b){
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }

六,快速排序

1,思想

我们知道,排好序的数组,对于其中的某个元素,该元素左边的元素一定小于等于该元素,右边一定大于等于该元素,快速排序就是根据这个特点找到每个元素的位置。
步骤:
1)选择一个基准,放到最后,左边一个标记,右边一个标记,
2)将左边标记移动,当遇到大于基准值的元素超过右边标记 时,停下;
3)将右标记移动,当遇到小于基准值的元素时 或 超过左边标记 时,停下;
4)如果左边标记没有超过右边标记,则交换左右标记的值,执行步骤2;
5)如果左边标记超过右边标记,则将基准值和左边标记交换(不能和右边标记交换,因为我们一开始选择的基准值是放到最后最后这个位置是属于右边的,必须大于等于基准值,同理,如果基准值在左边,则只能和右边标记交换),结束,此时找到了基准在数组中的正确位置。

2,图解

3,实现

   /**
     * 快速排序
     * @param arr
     * @param start 0
     * @param end arr.length-1
     */
    public static void sort(int[] arr,int start,int end){
        if(start >= end){
            return;
        }
        int i=start,j=end-1,key=arr[end];
        while(true){
            while(i<=j && key >= arr[i]){
                i++;
            }
            while(i<=j && key <= arr[j]){
                j--;
            }
            if(i<j){
                swap(arr,i,j);
            }else{
                swap(arr,i,end);
                break;
            }
        }
        sort(arr,start,i-1);
        sort(arr,i+1,end);
    }

    /**
     * 交换元素
     */
    private static void swap(int[] arr,int a,int b){
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }

七,归并排序

1,思想

将有序的两个数组合并在一起
过程:
无序数组 =》 {3,2,4,1}

折中拆 =》{3,2},{4,1}
折中拆 =》{3},{2},{4},{1}
拆到元素只有一个就停下
合,合并后保证有序,比如{3},{2}合并后不是{3,2},而是{2,3}
两两合并=》{2,3},{1,4}
两两合并=》{1,2,3,4}

2,图解

3,实现

   /**
     * 归并排序
     * @param arr
     * @param left
     * @param right
     */
    public static void sort(int[] arr, int left, int right){
        if(left < right){
            //  折中拆
            int mid = (left + right) / 2;
            sort(arr, left, mid);
            sort(arr, mid + 1, right);
            //  注意只能是mid + 1,换成mid的话,最后只能拆分到两个元素,而我们要的是拆分到一个元素
            merge(arr, left, mid + 1, right); // mid + 1
        }
    }

    /**
     * 合并
     * @param arr
     * @param left
     * @param mid
     * @param right
     */
    private static void merge(int[] arr,int left,int mid,int right){
        int[] tmpArr = new int[right - left + 1];
        int tmpLength = 0, leftEnd = mid - 1, left1 = left;
        while(left <= leftEnd && mid <= right){
            if(arr[left] <= arr[mid]){
                tmpArr[tmpLength++] = arr[left++];
            }else{
                tmpArr[tmpLength++] = arr[mid++];
            }
        }
        while(left <= leftEnd){
            tmpArr[tmpLength++] = arr[left++];
        }
        while(mid <= right){
            tmpArr[tmpLength++] = arr[mid++];
        }
        for(int i = 0; i < tmpLength; i++){
            arr[left1++] = tmpArr[i];
        }
    }

    /**
     * 交换元素
     */
    private static void swap(int[] arr,int a,int b){
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值