数据结构八大排序——java代码实现

分类时间复杂度空间复杂度稳定性
最好平均最坏
插入排序直接插入排序O(n)O(n2)O(n2)O(1)稳定
希尔排序O(n)O(n1-2)O(n2)O(1)不稳定
选择排序简单选择排序O(n2)O(n2)O(n2)O(1)不稳定
堆排序O(nlog2n)O(nlog2n)O(nlog2n)O(1)不稳定
交换排序冒泡排序O(n)O(n2)O(n2)O(1)稳定
快速排序O(nlog2n)O(nlog2n)O(n2)O(nlog2n)不稳定
归并排序O(nlog2n)O(nlog2n)O(nlog2n)O(n)稳定
基数排序O(d*(n+r)),d是长度,
r是基数,n是关键字个数
O(d*(n+r))O(d*(n+r))O(r+n)稳定

直接插入排序

思想:每次将待排序数组的第一个最小(大)值插入到已排序数组中

public void insertSort(int[] arr) {
	int temp, j;
	for (int i = 1; i < arr.length; i++) {
		temp = arr[i];	// 记录待排序数组的 第一个数据
		j = i - 1;
		while (j >= 0 && arr[j] > temp) {  //逐个向前检查
			arr[j+1] = arr[j];
			j--;
		}
		arr[j + 1] = temp;	// 插入到合适的位置
	}
}

希尔排序

思想:将数组按照增量gap分组,每组组内使用直接插入排序,再逐步缩小增量,直到增量==1为止

public void shellSort(int[] arr) {
	int gap = arr.length;
	while(gap>1){
		gap=gap/3+1;
		shell(arr,gap);
	}
}

// 直接插入排序中相当于gap==1
public void shell(int[] arr, int gap) {
	int temp,j;
	for(int i=gap; i<arr.length; i++){
		temp = arr[i];
		j = i-gap;
		while(j>=0 && arr[j]>temp){
			arr[j+gap] = arr[j];
			j-=gap;
		}
		arr[j+gap] = temp;
	}
}

简单选择排序

思路:每次遍历待排序数组,将其中的最小值放到数组第一位

public void selectSort(int[] arr) {
	for (int i = 0; i < arr.length; i++) {
		for(int j=i+1; j<arr.length; j++){
			if(arr[i]>arr[j]){
				swap(arr,i,j);
            }
        }
    }
}

堆排序

思路:

public static void heapSort(int[] arr) {
    //  p 指向父节点,从最后一个 非叶子节点 调整到根节点
    for (int p = arr.length / 2 - 1; p >= 0; p--) {
        buildTree(arr, p, arr.length);
    }
    int length = arr.length;
    while (length > 1) {
        swap(arr, 0, length - 1);
        length--;
        buildTree(arr, 0, length);
    }
}
public static void buildTree(int[] arr, int p, int length) {
    for (int i = 2 * p + 1; i < length; i = 2 * i + 1) {
    	// 如果右子树大于左子树,则用右子树进行比较
        if (i + 1 < length && arr[i] < arr[i + 1]) i++;
        if (arr[p] < arr[i]) {
            swap(arr, i, p);
            p = i;
        } else {
            break;
        }
    }
}

冒泡排序

思路:在待排序数组中,通过交换,每一次遍历使最大的数放到数组中的最后一位

public void bubbleSort(int[] arr) {
	for (int i = 1; i < arr.length; i++) {
        for(int j = 0; j<arr.length-i; j++){
            if(arr[j]>arr[j+1]){
                swap(arr,j,j+1);
            }
        }
    }
}

快速排序

思路:选择一个基准(一般为第一个或者最后一个数),在经过一次遍历后,数组左边所有数小于这个基准,右边所有数大于这个基准,但是都是无序的,再通过递归排序左右两个数组。

public void quickSort(int[] arr,int start, int end) {
	if(start>=end)
        return;
    int temp = arr[start];  //基准
    int left = start;
    int right = end;
    while(left<right){		// 将小于temp的数放在左边,大于temp的数放在右边
        while(left<right && arr[right]>=temp) right--;  //找到右边第一个小于temp的数
        while(left<right && arr[left]<=temp) left++;	//找到左边第一个大于temp的数
        if(left<right){
            swap(arr,left,right);
        }
    }
    arr[start] = arr[left];    	
    arr[left] = temp;			// 将arr[left]与arr[start]交换位置,
    quickSort(arr, start, left-1);
    quickSort(arr, left+1, end);
}

归并排序

思路:先把数组拆分为若干个子序列,并将子序列排序后再合并为完整的序列
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

public void mergeSort(int[] arr, int start, int end) {
	if (start >= end)
        return;
    int mid = start + (end - start) / 2;
    mergeSort(arr, start, mid);
    mergeSort(arr, mid + 1, end);	// 先进行拆分
    merge(arr, start, mid, end);	// 合并
}
public void merge(int[] arr, int start, int mid, int end){
	int[] temp = new int[end - start + 1];	//创建一个空数组用于排序
    int left = start;
    int right = mid + 1;
    int index = 0;
    // 将数组分为左右两部分,并逐个比较,按顺序放入temp数组中
    while (left <= mid && right <= end) {
        if (arr[left] < arr[right]) {
            temp[index++] = arr[left++];
        } else {
            temp[index++] = arr[right++];
        }
    }
    // 当左半部分或者右半部分全放入temp中后,检查左右两部分是否还仍有未放入temp的数
    while (left <= mid) {
        temp[index++] = arr[left++];
    }
    while (right <= end) {
        temp[index++] = arr[right++];
    }
    for (int i = 0; i < temp.length; i++) {
        arr[i + start] = temp[i];	// 将temp返回至arr
    }
}

基数排序

思路:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

public void baseSort(int[] arr) {
	int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        max = Math.max(max, arr[i]);
    }
    int maxLength = (max + "").length();  //计算数组中最大数字的位数
    int[][] bucket = new int[10][arr.length]; 	//存放数字 
    int[] elementCount = new int[10];			//计数
    int n = 1;
    for (int i = 0; i < maxLength; i++) {
        for (int value : arr) {
            int element = value/n%10;
            bucket[element][elementCount[element]]=value;
            elementCount[element]++;
        }
        int index = 0;
        for (int j = 0; j < elementCount.length; j++) {
            if(elementCount[j]!=0){
                for (int k = 0; k < elementCount[j]; k++) {
                    arr[index++] = bucket[j][k];	//将桶中的数据放回arr
                }
            }
            elementCount[j]=0;	//计数器全归0
        }
        n*=10;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值