首页 > 系统相关 >java常见的排序算法(冒泡排序、选择排序、插入排序、shell排序、归并排序、堆排序、快速排序)介绍

java常见的排序算法(冒泡排序、选择排序、插入排序、shell排序、归并排序、堆排序、快速排序)介绍

时间:2023-07-31 16:32:40浏览次数:38  
标签:index arr shell temp int 冒泡排序 排序 效率



文章目录

  • 一、冒泡排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 二、选择排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 三、插入排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 四、shell排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 五、归并排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 六、快速排序
  • 1、效率表现和适用范围
  • 2、算法实现
  • 七、堆排序
  • 1、效率表现和适用范围
  • 2、算法实现



本文简单的介绍了java常见的几种排序。
所有的排序均是一个数组由小到大进行排序。

一、冒泡排序

1、效率表现和适用范围

效率 O(n²)
适用于排序小列表

2、算法实现

public void bubbleSortArray(int[] a) {
		int n = a.length;
		for (int i = 1; i < n; i++) {
			for (int j = 0; i < n - i; j++) {
				// 比较交换相邻元素
				if (a[j] > a[j + 1]) {
					int temp;
					temp = a[j];
					a[j] = a[j + 1];
					a[j + 1] = temp;
				}
			}
		}

	}

二、选择排序

1、效率表现和适用范围

效率O(n²)
适用于排序小的列表

2、算法实现

public void selectSortArray(int[] a) {
		int n = a.length;
		int min_index;

		for (int i = 0; i < n - 1; i++) {
			min_index = i;
			for (int j = i + 1; j < n; j++)// 每次扫描选择最小项 
				if (a[j] < a[min_index])
					min_index = j;
			if (min_index != i)// 找到最小项交换,即将这一项移到列表中的正确位置 
			{
				int temp;
				temp = a[i];
				a[i] = a[min_index];
				a[min_index] = temp;
			}
		}
	}

三、插入排序

1、效率表现和适用范围

最佳效率O(n);最糟效率O(n²)与冒泡、选择相同
适用于排序小列表
若列表基本有序,则插入排序比冒泡、选择更有效率

2、算法实现

void insertSortArray(int[] a) {
		int n = a.length;
		for (int i = 1; i < n; i++)// 循环从第二个数组元素开始,因为a[0]作为最初已排序部分
		{
			int temp = a[i];// temp标记为未排序第一个元素
			int j = i - 1;
			while (j >= 0 && a[j] > temp)/* 将temp与已排序元素从小到大比较,寻找temp应插入的位置 */
			{
				a[j + 1] = a[j];
				j--;
			}
			a[j + 1] = temp;
		}
	}

四、shell排序

1、效率表现和适用范围

适用于排序小列表。
效率估计O(nlog2n)~O(n1.5),取决于增量值的最初大小。建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
壳(Shell)排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃

2、算法实现

void shellSortArray(int[] a) {
		int n = a.length;
		for (int incr = 3; incr < 0; incr--)// 增量递减,以增量3,2,1为例
		{
			for (int L = 0; L < (n - 1) / incr; L++)// 重复分成的每个子列表
			{
				for (int i = L + incr; i < n; i += incr)// 对每个子列表应用插入排序
				{
					int temp = a[i];
					int j = i - incr;
					while (j >= 0 && a[j] > temp) {
						a[j + incr] = a[j];
						j -= incr;
					}
					a[j + incr] = temp;
				}
			}
		}
	}

五、归并排序

1、效率表现和适用范围

效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
适用于排序大列表,基于分治法

2、算法实现

public static void merge(int[] arr, int low, int mid, int high, int[] tmp) {
		int i = 0;
		int j = low, k = mid + 1; // 左边序列和右边序列起始索引
		while (j <= mid && k <= high) {
			if (arr[j] < arr[k]) {
				tmp[i++] = arr[j++];
			} else {
				tmp[i++] = arr[k++];
			}
		}
		// 若左边序列还有剩余,则将其全部拷贝进tmp[]中
		while (j <= mid) {
			tmp[i++] = arr[j++];
		}

		while (k <= high) {
			tmp[i++] = arr[k++];
		}

		for (int t = 0; t < i; t++) {
			arr[low + t] = tmp[t];
		}
	}

	/**
	 * 效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。  适用于排序大列表,基于分治法
	 * 
	 * @param arr
	 * @param low
	 * @param high
	 * @param tmp
	 */
	public static void mergeSort(int[] arr, int low, int high, int[] tmp) {
		if (low < high) {
			int mid = (low + high) / 2;
			mergeSort(arr, low, mid, tmp); // 对左边序列进行归并排序
			mergeSort(arr, mid + 1, high, tmp); // 对右边序列进行归并排序
			merge(arr, low, mid, high, tmp); // 合并两个有序序列
		}
	}

六、快速排序

1、效率表现和适用范围

快速排序的算法思想:选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。
平均效率O(nlogn),适用于排序大列表。
此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
基于分治法。

2、算法实现

public static void quickSort(int[] arr, int low, int high) {
		int i, j, temp, t;
		if (low > high) {
			return;
		}
		i = low;
		j = high;
		// temp就是基准位
		temp = arr[low];

		while (i < j) {
			// 先看右边,依次往左递减
			while (temp <= arr[j] && i < j) {
				j--;
			}
			// 再看左边,依次往右递增
			while (temp >= arr[i] && i < j) {
				i++;
			}
			// 如果满足条件则交换
			if (i < j) {
				t = arr[j];
				arr[j] = arr[i];
				arr[i] = t;
			}

		}
		// 最后将基准为与i和j相等位置的数字交换
		arr[low] = arr[i];
		arr[i] = temp;
		// 递归调用左半数组
		quickSort(arr, low, j - 1);
		// 递归调用右半数组
		quickSort(arr, j + 1, high);
	}

七、堆排序

最大堆:后者任一非终端节点的关键字均大于或等于它的左、右孩子的关键字,此时位于堆顶的节点的关键字是整个序列中最大的。
思想:
(1)令i=l,并令temp= kl ;
(2)计算i的左孩子j=2i+1;
(3)若j<=n-1,则转(4),否则转(6);
(4)比较kj和kj+1,若kj+1>kj,则令j=j+1,否则j不变;
(5)比较temp和kj,若kj>temp,则令ki等于kj,并令i=j,j=2i+1,并转(3),否则转(6)
(6)令ki等于temp,结束。

1、效率表现和适用范围

堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为O(1),它是不稳定的排序方法。

  • 堆排序与直接插入排序的区别
    1、直接选择排序中,为了从R[1…n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2…n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
    2、堆排序可通过树形结构保存部分比较结果,可减少比较次数。

2、算法实现

public static void heapSort(int[] arr) {
        int temp;
        System.out.println("从后向前构建堆");
        //从后面的非叶子结点进行调整数组为大顶堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            System.out.println("非叶子结点:" + i);
            bigTopPile(arr, i, arr.length);
        }
        System.out.println("从根节点开始构建堆");
        for (int j = arr.length - 1; j > 0; j--) {
            temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            System.out.println("确认下标为" + j + ":" + Arrays.toString(arr));
            // 从根节点开始调整数据为大顶堆
            bigTopPile(arr, 0, j);
        }
    }

    /**
     * 将数组变为一个大顶堆
     *
     * @param arr         数组
     * @param nonLeafNode 非叶子结点在数组中的下标
     * @param length      调整的数组长度
     */
    public static void bigTopPile(int[] arr, int nonLeafNode, int length) {
        System.out.println("构建前数组:" + Arrays.toString(arr));
        //保存非叶子结点
        int temp = arr[nonLeafNode];
        System.out.println("非叶子结点数据:" + temp);

        // index = nonLeafNode * 2 + 1 index为非叶子结点的左子结点
        for (int index = nonLeafNode * 2 + 1; index < length; index = index * 2 + 1) {
            System.out.println("左子节点:" + index);
            //左子节点小于右子节点  右子节点就是左子节点加1
            if (index + 1 < length && arr[index] < arr[index + 1]) {
                System.out.println("左子节点小于右子节点,指针指向右子节点");
                //左子节点小于右子节点 那么将index此时指向右子节点
                index++;
            }
            //如果子节点大于父节点  则进行交换
            if (arr[index] > temp) {
                System.out.println("子节点大于父节点,进行交换");
                arr[nonLeafNode] = arr[index];
                nonLeafNode = index;
            } else {
                break;
            }
        }
        arr[nonLeafNode] = temp;
        System.out.println("构建后数组:" + Arrays.toString(arr));
        System.out.println();
    }

以上,简单的介绍了java中常见的集中排序算法以及各自的效率表现、应用场景。


标签:index,arr,shell,temp,int,冒泡排序,排序,效率
From: https://blog.51cto.com/alanchan2win/6909705

相关文章

  • mysql 错误日志 shell
    实现MySQL错误日志shell的步骤为了实现MySQL错误日志shell,你可以按照以下步骤进行操作:步骤描述步骤一连接到MySQL数据库步骤二执行查询创建错误日志表步骤三创建一个触发器来捕获错误步骤四启用错误日志shell接下来,让我们逐步执行这些步骤。......
  • 【九】DRF之过滤排序异常
    【一】过滤(Filtering)对于列表数据可能需要根据字段进行过滤我们可以通过添加django-fitlter扩展来增强支持。pipinstalldjango-filter在配置文件中增加过滤后端的设置:INSTALLED_APPS=[...'django_filters',#需要注册应用,]REST_FRAMEWORK={......
  • Xshell使用是出现全黑或全白问题
    Xshell使用是出现全黑或全白问题,这是我实际遇到的问题如图。 解决方式:设置字体  解决成功: ......
  • 归并排序
    求逆序对我用的是归并排序直接上我在洛谷里做的那道逆序对的题目的归并排序主要代码吧1voidmsort(intl,intr){2if(l>=r)return;3intmid=(l+r)>>1;4msort(l,mid);5msort(mid+1,r);6inti=l,j=mid+1,k=l;7......
  • C#冒泡排序算法
    冒泡排序实现原理冒泡排序是一种简单的排序算法,其原理如下:从待排序的数组的第一个元素开始,依次比较相邻的两个元素。如果前面的元素大于后面的元素(升序排序),则交换这两个元素的位置,使较大的元素“冒泡”到右侧。继续比较下一对相邻元素,重复步骤2,直到遍历到数组的倒数第二......
  • 关于排序的一些小问题
    快速排序模板voidquick_sort(inta[],intl,intr){if(l>=r)return;inti=l-1,j=r+1;x=q[l+r>>1];while(i<j){doi++;while(a[i]<x);doj--;while(a[j]>x);if(i<j)swap(a[i],a[j]);quick_sort(a,l,j),quick_sort(a,j+1,......
  • FinalShell 下载和安装
    安装一、登录hostbuf.com网站跳转按钮点击第一条二、选择Windows下载地址复制粘贴到新的页面,自动开始下载![](https://img2023.cnblogs.com/blog/2913371/202307/2913371-20230730164726988-1684490782.png三、傻瓜式安装,一直点下一步,完成安装连接虚拟机一、打开虚......
  • 正点原子Ubuntu入门016---shell脚本条件判断、函数和循环
    一、shell脚本的条件判断虽然可以通过&&和||来实现简单的条件判断,但是稍微复杂的就不行了shell脚本呢提供了if  then 条件判断语句,写法:if条件判断;then//判断条件成立要做的事情fi   ifthenelse语法 if条件判断;then//判断条件成立要做的事情e......
  • Windows下让git shell中的git命令走代理
    最近用clash跑stable-diffusion,发现git不走代理,间而出现各种问题,故记录一下。假如只针对GitHub:gitconfig--globalhttp.https://github.com.proxyhttp://127.0.0.1:XXXXgitconfig--globalhttps.https://github.com.proxyhttps://127.0.0.1:XXXX假如使用sock5gitconfig......
  • CDP7环境下使用SparkSQL Shell方式
    相信很多在用CDP7的小伙伴都遇到了Spark里面不再支持spark-sql的问题这里给出两种解决方案:spark-submit与spark-shellcloudera官方给的解决方案https://docs.cloudera.com/cdp-private-cloud-base/7.1.5/developing-spark-applications/topics/spark-sql-example.html基于这个方案,......