数据结构中常见的内部排序算法:

  插入排序:直接插入排序、折半插入排序、希尔排序

  交换排序:冒泡排序、快速排序

  选择排序:简单选择排序、堆排序

  归并排序、基数排序、计数排序

直接插入排序

  思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到全部记录插入完成。

  性能:时间复杂度:最好o(n):有序,最坏o(n^2):逆序,平均o(n^2);空间复杂度o(1);稳定

   public int[] straightInsertSort(int array[]){
int temp;
for(int i=1; i<array.length; i++){ //依次对1到array.length-1个元素进行处理
temp = array[i];
for(int j=0; j<i; j++){ //已排好序的0到i-1个元素
if(temp < array[j]){ //插入位置j
for(int k=i-1;k>=j;k--){ //将j到i-1个元素向后移一个位置
array[k+1]=array[k]; //此时array[i]为已排好序的子数组中的最大值
}
array[j] = temp; //将第i个元素插入到位置j上
break;
}
}
}
return array;
}

折半插入排序:

  思想:利用折半查找的方法找出元素的待插入位置,然后再统一移动待插入位置之后的所有元素,最后将待插入元素插入到相应位置。

  性能:平均情况下,比较次数o(nlogn),移动次数o(n^2)

     时间复杂度:最好o(n):有序,最坏o(n^2):逆序,平均o(n^2);空间复杂度o(1);稳定

     public int[] binaryInsertSort(int[] array){
int temp,low,high;
for(int i=1; i<array.length; i++){
temp = array[i];
//从已排好序的0到i-1个元素中,折半查找出元素的待插入位置
low = 0;
high = i-1;
while(low <= high){
if(array[(low+high)/2] <= array[i]){
low = (low+high)/2 + 1;
}else{
high = (low+high)/2 - 1;
}
}
//移动待插入位置low到i-1间的所有元素
for(int j=i-1; j>=low; j-- ){
array[j+1] = array[j];
}
array[low] = temp;
}
return array;
}

希尔排序:

  思想:将排序表分割成若干个形如L[i,i+d,i+2d,...,i+kd]的“特殊”子表,分别进行直接插入排序,当整个表中元素已呈现“基本有序”时,再对全体记录进行一次直接插入排序(d=1时)。

     步长设置:d1=array.length/2;di=di/2,最后一个增量为1;

  性能:时间复杂度:最坏o(n^2),平均o(n^1.3),空间复杂度o(1),不稳定

 public int[] shellSort(int[] array){
for(int d=array.length/2; d>=1; d=d/2){ //用步长值来控制循环次数
for(int i=d;i<array.length;i++){
int temp = array[i];
if(temp < array[i-d]){ //将array[i]插入到有序增量子表中
int j;
for(j=i-d;j>=0 && temp<array[j];j-=d){
array[j+d]=array[j]; //记录后移,寻找插入位置
}
array[j+d] = temp;
}
}
}
return array;
}

冒泡排序:

  思想:对于待排序表,从前往后两两比较相邻元素的值,若为逆序,则交换,直到序列比较完成。如此,每次冒泡即可得到当前待排表中的最大元素,并已放置在相应的位置。

  性能:时间复杂度:最好o(n)有序,最坏o(n^2)逆序,平均o(n^2),空间复杂度o(1),稳定

     public int[] bubbleSort(int[] array){
boolean flag = false; //用来标记该序列是否已是有序
for(int i=0;i<array.length-1;i++){ //做n-1趟冒泡
for(int j=0;j<array.length-i-1;j++){
if(array[j]>array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = true; //有元素交换,则该序列初始状况不是有序的
}
}
if(flag == false){ //本趟遍历后没有发生交换,说明表已经有序
return array;
}
}
return array;
}

快速排序:

  思想:基于分治的思想:在待排序表中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分,使得一部分中所有元素小于等于pivot,另一部分中所有元素大于pivot,则pivot放在了其最终位置上,这个过程称为一趟快速排序。而后递归地对两个子表重复上述过程,直到每部分内只有一个元素或空为止。

  性能: 空间复杂度:需要递归工作栈:最坏o(n),平均o(logn)

      时间复杂度:最坏:o(n^2)初始表基本有序或基本逆序,平均o(n*logn)

      不稳定

   public int[] quickSort(int[] array,int low,int high){
if(low<high){ //递归跳出的条件
int mid= partition(array, low, high); //划分,得到枢值所在的下表
quickSort(array,low,mid-1); //依次对两个子表进行递归排序
quickSort(array,mid+1,high);
}
return array;
}
//快速排序的划分函数
public int partition(int[] array,int low, int high){
int pivot = array[low]; //每次取数组中的第一个元素为基准
while(low < high){ //跳出循环的条件
while(low<high && array[high] > pivot){ //从右边开始找到第一个小于或等于pivot的值
high--;
}
while(low<high && array[low] < pivot){ //从左边开始找到第一个大于或等于pivot的值
low++;
}
int temp = array[low]; //交换
array[low] = array[high];
array[high] = temp;
if(low<high && array[low] == pivot && array[high] == pivot){ //特殊情况
low++;
}
}
return low;
}

简单选择排序:

  思想:假设排序表array[0,...,n-1],第 i 趟排序即从array[0,...,n-1]中选择关键字最小的元素与array[i]交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟派克就可以使整个序列有序。

  性能:时间复杂度:o(n^2),空间复杂度o(1),不稳定

    public int[] simpleSelectSort(int[] array){
for(int i=0;i<array.length -1;i++){ //一共进行n-1趟
int min = i; //记录最小元素位置
for(int j=i+1;j<array.length;j++){ //在array[i,...,n-1]中选择最小的元素
if(array[j] < array[min]){
min = j; //更新最小元素的位置
}
}
int temp = array[i]; //将最小元素与第i个位置交换
array[i] = array[min];
array[min] = temp;
}
return array;
}

堆排序:Java实现堆排序(大根堆)

归并排序:

  思想:“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。假设待排序表含有n个记录,则可以看成是n个有序的子表,每个子表的长度为1,然后两两归并,得到(n/2)个长度为2或1的有序表;再两两归并,...,如此重复,直到合并成一个长度为n的有序表为止,这种排序方法称为2-路归并排序。

  递归形式的2-路归并排序算法是基于分治的,其过程如下:

    分解:将含有n个元素的待排序表分成各含有n/2个元素的子表,采用2-路归并排序算法对两个子表递归地进行排序;

    合并:合并两个已排序的子表得到排序结果。

  性能:空间复杂度:o(n);时间复杂度:o(nlogn);稳定

   public int[] mergeSort(int[] array,int low, int high){
if(low < high){ //递归结束的条件
int mid = (low + high)/2; //二路归并排序,从中间划分两个子序列【分解过程】
mergeSort(array, low, mid); //对左侧子序列进行递归排序
mergeSort(array, mid+1, high); //对右侧子序列进行递归排序
merge(array,low,mid,high); //归并【合并过程】
}
return array;
} //将前后相邻的两个有序表归并为一个有序表
private void merge(int[] array,int low, int mid, int high){
int[] tempArray = new int[array.length]; //辅助数组tempArray
for(int i=low;i<=high;i++){ //将array数组中[low...high]的元素复制到辅助数组tempArray中
tempArray[i] = array[i];
}
int i,j,k;
for(i=low,j=mid+1,k=i;i<=mid && j<=high;k++){
if(tempArray[i]>tempArray[j]){ //比较tempArray的左右两端中的元素
array[k] = tempArray[j++]; //将较小值复制到array中
}else{
array[k] = tempArray[i++];
}
}
while(i<=mid){ //若第一个表未检测完,复制
array[k++] = tempArray[i++];
}
while(j<=high){ //若第二个表未检测完,复制
array[k++] = tempArray[j++];
}
}

基数排序:

  基于计数排序实现: Java实现基于桶式排序思想和计数排序思想实现的基数排序

  基于队列辅助实现:

  思想:基数排序不是基于比较进行排序的,而是采用多关键字排序思想,借助“分配”和“收集”两种操作对单逻辑关键字进行排序。

      基数排序是利用多关键字先达到局部有序,再调整达到全局有序。

  性能:空间复杂度:o(r);时间复杂度:o(d(n+r));稳定

     其中,r为基数,d为最大关键字的位数(决定了排序的趟数),n为待排序列表中元素的个数。

       //基于队列辅助实现的基数排序
1 public int[] radixSort(int[] array){
//找到待排序序列中的最大元素
int max = array[0];
for(int i=1; i<array.length;i++){
if(array[i] > max){
max = array[i];
}
}
//确定最大元素的位数maxBits
int maxBits = 0;
while(max > 0){
max = max/10;
maxBits ++;
} //建立10个队列
Queue<Integer>[] queue = new LinkedList[10];
for(int i=0; i<queue.length; i++){
queue[i] = new LinkedList<Integer>();
} //进行maxBits次分配和收集
for(int i=0; i<maxBits;i++){
//分配数组
for(int j=0; j<array.length;j++){
//得到元素的第maxBits位,然后将该元素插入到对应的位置
queue[(array[j] % (int)Math.pow(10, i+1))/(int)Math.pow(10, i)].add(array[j]);
}
//元素计数器
int count = 0;
//收集队列元素
for(int k=0;k<queue.length;k++){
while(queue[k].size() > 0){
array[count++] = queue[k].poll().intValue();
}
}
}
return array;
}

计数排序:

  前提:待排序表中的所有待排序关键字必须互不相同;

  思想:计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,则该记录在新的有序表中的存放位置即为c。

  性能:空间复杂度:o(n);时间复杂度:o(n^2);

     public int[] countSort(int[] array){
int[] tempArray = new int[array.length]; //引入辅助数组
for(int i=0;i<array.length;i++){
int count = 0;
for(int j=0;j<array.length;j++){
if(array[i]>array[j]){
count++;
}
}
tempArray[count] = array[i];
}
return tempArray;
}

Java实现各种内部排序算法的更多相关文章

  1. Java 的八种排序算法

    Java 的八种排序算法 这个世界,需要遗忘的太多. 背景:工作三年,算法一问三不知. 一.八种排序算法 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序. 二.算 ...

  2. 常见内部排序算法对比分析及C++ 实现代码

    内部排序是指在排序期间数据元素全部存放在内存的排序.外部排序是指在排序期间全部元素的个数过多,不能同时存放在内存,必须根据排序过程的要求,不断在内存和外存之间移动的排序.本次主要介绍常见的内部排序算法 ...

  3. 用 Java 实现常见的 8 种内部排序算法

    一.插入类排序 插入类排序就是在一个有序的序列中,插入一个新的关键字.从而达到新的有序序列.插入排序一般有直接插入排序.折半插入排序和希尔排序. 1. 插入排序 1.1 直接插入排序 /** * 直接 ...

  4. Java实现八种排序算法(代码详细解释)

    经过一个多星期的学习.收集.整理,又对数据结构的八大排序算法进行了一个回顾,在测试过程中也遇到了很多问题,解决了很多问题.代码全都是经过小弟运行的,如果有问题,希望能给小弟提出来,共同进步. 参考:数 ...

  5. Java实现十个经典排序算法(带动态效果图)

    前言 排序算法是老生常谈的了,但是在面试中也有会被问到,例如有时候,在考察算法能力的时候,不让你写算法,就让你描述一下,某个排序算法的思想以及时间复杂度或空间复杂度.我就遇到过,直接问快排的,所以这次 ...

  6. java基础---数组的排序算法(3)

    一.排序的基本概念 排序:将一个数据元素集合或序列重新排列成按一个数据元素某个数据项值有序的序列 稳定排序:排序前和排序后相同元素的位置关系与初始序列位置一致(针对重复元素来说,相对位置不变) 不稳定 ...

  7. java SE 常用的排序算法

    java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) ...

  8. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  9. 数据结构(三) 用java实现七种排序算法。

    很多时候,听别人在讨论快速排序,选择排序,冒泡排序等,都觉得很牛逼,心想,卧槽,排序也分那么多种,就觉得别人很牛逼呀,其实不然,当我们自己去了解学习后发现,并没有想象中那么难,今天就一起总结一下各种排 ...

随机推荐

  1. 31_网络编程(Socket套接字编程)_讲义

    今日内容介绍 1.网络三要素及传输协议 2.实现UDP协议的发送端和接收端 3.实现TCP协议的客户端和服务器 4.TCP上传文件案例 01网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用 ...

  2. PyCharm 配置远程python解释器和在本地修改服务器代码

    PyCharm 配置远程python解释器和在本地修改服务器代码 最近在学习机器学习的过程中,常常需要将本地写的代码传到GPU服务器中,然后在服务器上运行.之前的做法一直是先在本地写好代码,然后通过F ...

  3. java synchronized关键字浅析

    synchronized这个关键字想必学Java的人都应该知道. 直接上例子: 方法级别实例 public class AtomicInteger { private int index; publi ...

  4. Delphi控件-复合控件【转】

    复合控件复合控件是Delphi控件中非常重要的一种控件,复合控件就是将两个或两个以上的控件重新组合成一个新的控件.例如TspinEdit.TlabeledEdit.TDBNavigator等就是复合控 ...

  5. HBase 架构与工作原理5 - Region 的部分特性

    本文系转载,如有侵权,请联系我:likui0913@gmail.com Region Region 是表格可用性和分布的基本元素,由列族(Column Family)构成的 Store 组成.对象的层 ...

  6. set_magic_quotes_runtime

    在php的配置文件中,有个布尔值的设置,就是magic_quotes_runtime,当它打开时,php的大部分函数自动的给从外部引入的(包括数据库或者文件)数据中的溢出字符加上反斜线. 当然如果重复 ...

  7. [转帖]SSD的工作原理、GC和TRIM、写入放大以及性能评测

    SSD的工作原理.GC和TRIM.写入放大以及性能评测 https://blog.csdn.net/scaleqiao/article/details/50511279   SSD的物理结构和工作原理 ...

  8. 【转】正确的 Composer 扩展包安装方法

    简单解释 composer install - 如有 composer.lock 文件,直接安装,否则从 composer.json 安装最新扩展包和依赖: composer update - 从 c ...

  9. sklearn-特征工程之特征选择

    title: sklearn-特征工程之特征选择 date: 2016-11-25 22:49:24 categories: skearn tags: sklearn --- 抄袭/参考资料 使用sk ...

  10. C++模板学习笔记

    一个有趣的东西:实现一个函数print, 输入一个数组, 输出数组的各个维度长度. eg. ], b[][], c[][][]; print(a); //(2, 4) print(b); //(3, ...