排序算法

算法时间复杂度分析方法:

在这里插入图片描述

在这里插入图片描述

a 为子问题的个数 n/b 为子问题的规模大小 f(n)为子问题的时间复杂度

1. 直接插入排序:

算法思想:

​ 外层循环 1~n来遍历数组的每一个元素;遍历到当前元素时,首先需要设置哨兵来记录当前的值(tmp),然后依次比较前面的所有元素值,比较后进行移动处理。

算法时间复杂度:

​ 设总共有n个元素,则算法会执行n-1趟,最坏条件下当处理到第i个元素时需要和前(0 ~ i-1)个元素都进行比较,复杂度如下图。最坏条件下还需要将前 i 个元素都往后挪动一个单位(同时每轮需要加上哨兵设置复杂度1、找到位置后的插入复杂度1)。

在这里插入图片描述

(ps: 图片引用自 https://blog.csdn.net/qq_37623612/article/details/80312121 )

   public void InsertSort(int arr[]) {
	   int i,j,tmp;
	   for(i=1;i<arr.length;i++) {
		   //用tmp来记载arr[i]处的元素值(哨兵)
		   tmp=arr[i];
		   j=i;
		   
		   //tmp<arr[j-1]:将比tmp值大的往后移动(求出的是正序排序)   |  tmp>arr[j-1]:将比tmp值小的往后移动(求出的是逆序排序)
		   while(j>0 && tmp<arr[j-1]) {
			   arr[j]=arr[j-1];
			   j--;
		   }
		   arr[j]=tmp;
	   }
   }

2. 快速排序:

算法思想:

​ 每次比较数组头的元素值应该插入的位置,通过与当前数组的头和尾的大小比较来进行元素移动,将比当前元素值大的移动到后面,比当前元素值小的移动到前面,最终得到当前元素值的位置index。最后再递归地去调用排序算法进行从(start ~ index-1) 与 (index+1 ~ end)的排序。

算法时间复杂度:

​ 采用主方法来计算,每次一分为2进行比较,子问题规模为原问题规模的一半,那么a=2 b=2,f(n)=n;那么结果计算为 T[n]= 2T[n/2] + f(n),采用主方法比较得到时间复杂度为 O(nlog n)

public int getIndex(int arr[],int start,int end) {
	int temp =arr[start];
	while(start<end) {
		while(start<end && arr[end]>=temp) {      //注意每次都是和temp比较
			end--;
		}
		arr[start]=arr[end];
		while(start<end && arr[start]<=temp) {
			start++;
		}
		arr[end]=arr[start];
	}
	arr[start]=temp;
	return start;
}

public void quickSort(int arr[],int start,int end) {
	if(start<end) {
		int index=getIndex(arr, start, end);
		quickSort(arr, start, index-1);   //注意这里是start,而不是0,那样会降低效率
		quickSort(arr, index+1,end);
	}
}

@Test
public void test() {
	int arr[]= {2,5,3,1,15,12,42,98,79};
	quickSort(arr, 0, arr.length-1);
	System.out.println(Arrays.toString(arr));
}

3. 堆排序:

 引用自:https://blog.csdn.net/ns_code/article/details/20227303?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.add_param_isCf&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.add_param_isCf

/*******************************
		    堆排序
Author:兰亭风雨 Date:2014-02-27
Email:zyb_maodun@163.com
********************************/
#include<stdio.h>
#include<stdlib.h>
 
/*
arr[start+1...end]满足最大堆的定义,
将arr[start]加入到最大堆arr[start+1...end]中,
调整arr[start]的位置,使arr[start...end]也成为最大堆
注:由于数组从0开始计算序号,也就是二叉堆的根节点序号为0,
因此序号为i的左右子节点的序号分别为2i+1和2i+2
*/
void HeapAdjustDown(int *arr,int start,int end)
{
	int temp = arr[start];	//保存当前节点
	int i = 2*start+1;		//该节点的左孩子在数组中的位置序号
	while(i<=end)
	{
		//找出左右孩子中最大的那个
		if(i+1<=end && arr[i+1]>arr[i])  
			i++;
		//如果符合堆的定义,则不用调整位置
		if(arr[i]<=temp)	
			break;
		//最大的子节点向上移动,替换掉其父节点
		arr[start] = arr[i];
    //继续往下遍历
		start = i;
		i = 2*start+1;
	}
	arr[start] = temp;
}
 
/*
堆排序后的顺序为从小到大
因此需要建立最大堆
*/
void Heap_Sort(int *arr,int len)
{
	int i;
	//把数组建成为最大堆
	//第一个非叶子节点的位置序号为len/2-1
	for(i=len/2-1;i>=0;i--)
		HeapAdjustDown(arr,i,len-1);
	//进行堆排序
	for(i=len-1;i>0;i--)
	{
		//堆顶元素和最后一个元素交换位置,
		//这样最后的一个位置保存的是最大的数,
		//每次循环依次将次大的数值在放进其前面一个位置,
		//这样得到的顺序就是从小到大
		int temp = arr[i];
		arr[i] = arr[0];
		arr[0] = temp;
		//将arr[0...i-1]重新调整为最大堆
		HeapAdjustDown(arr,0,i-1);
	}
}
}

4. 归并排序:

import org.junit.Test;
public class MergeSort {
    //两路归并算法,两个排好序的子序列合并为一个子序列
    public void merge(int []a,int left,int mid,int right){
        int []tmp=new int[a.length];//辅助数组
        int p1=left,p2=mid+1,k=left;//p1、p2是检测指针,k是存放指针

        while(p1<=mid && p2<=right){
            if(a[p1]<=a[p2])
                tmp[k++]=a[p1++];
            else
                tmp[k++]=a[p2++];
        }

        while(p1<=mid) tmp[k++]=a[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
        while(p2<=right) tmp[k++]=a[p2++];//同上

        //复制回原素组
        for (int i = left; i <=right; i++) 
            a[i]=tmp[i];
    }

    public void mergeSort(int [] a,int start,int end){
        if(start<end){//当子序列中只有一个元素时结束递归
            int mid=(start+end)/2;//划分子序列
            mergeSort(a, start, mid);//对左侧子序列进行递归排序
            mergeSort(a, mid+1, end);//对右侧子序列进行递归排序
            merge(a, start, mid, end);//合并
        }
    }

    @Test
    public void test(){
        int[] a = { 49, 38, 65, 97, 76, 13, 27, 50 };
        mergeSort(a, 0, a.length-1);
        System.out.println("排好序的数组:");
        for (int e : a)
            System.out.print(e+" ");
    }
}

在这里插入图片描述
图片引用自: https://blog.csdn.net/qq_43684985

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值