以下程序均将数据封装于DataWrap数据包装类中,如下所示:

 //数据包装类
class DataWrap implements Comparable<DataWrap>
{
int data;
String flag;
public DataWrap(int data,String flag)
{
this.data = data;
this.flag = flag;
}
//重写compareTo方法
public int compareTo(DataWrap other)
{
return this.data > other.data ? 1 : (this.data == other.data ? 0 : -1);
}
public String toString()
{
return this.data + this.flag;
}
}

一、选择排序

1、直接选择排序

  数组分成有序区和无序区,初始时整个数组都是无序区,然后每次从无序区选一个最小的元素直接放到有序区的最后,直到整个数组变有序区。

 public static void directSelectSort(DataWrap[] dw)
{
int n = dw.length;
for(int i = 0;i < n-1;i++)
{
int minIndex = i;
for(int j = i+1;j < n;j++)
{
if(dw[minIndex].compareTo(dw[j]) > 0)
{
minIndex = j; //minIndex为每趟比较重最小数的索引
}
}
swap(dw,minIndex,i);
System.out.println("直接选择排序中的元素:" + Arrays.toString(dw));
} }

2、堆排序

  1)二叉堆

    二叉堆是完全二叉树或者是近似完全二叉树。

    父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

    每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

   当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。

  2)堆的存储

    一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

   3)堆排序原理(以最小堆为例)

    堆排序是先建立一个最小堆,然后第一次将A[0]与A[n - 1]交换,再对A[0…n-2]重新恢复最小堆。第二次将A[0]与A[n – 2]交换,再对A[0,…,n - 3]重新

  恢复最小堆,重复这样的操作直到A[0]与A[1]交换。由于每次都是将最小的数据并入到后面的有序区间,故操作完成后整个数组就有序(为降序)了。

建立最小堆就是先从最后一个非叶子节点(即n/2-1节点)开始,节点依次往前就行,直到第二个节点。对于每个节点,先比较其左右节点选出较小的节点,然后

将较小的节点与父节点进行比较。如果父节点比最小的子节点还小的话则不需要调整,否则的话将较小的子节点作为新的父节点,将原先的父节点与其子节点的子节

点中较小的进行比较,直到该父节点找到能够插入的位置或者是到达堆的结束。

  4)代码实现

 public class HeapSort
{
/**
* 从某一节点向下调整大小
* @param dw 待排序数据包
* @param i 开始向下调整的堆索引
* @param n 所调整堆数据的大小
*/
public static void MinHeapFixDown(DataWrap[] dw,int i,int n)
{
int j;
DataWrap temp;
j = 2 * i +1;
temp = dw[i];
while(j < n)
{
if(j+1 < n && dw[j+1].compareTo(dw[j]) < 0)
{ //找出左右子节点中较小的
j++;
}
if(temp.compareTo(dw[j]) <= 0)
{ //将父节点与子节点进行比较
break;
}
dw[i] = dw[j]; //将较小的子节点上移
i = j;
j = 2 * i +1;
}
dw[i] = temp;
}
//构建最小堆并进行堆排序
public static void heapSort(DataWrap[] dw)
{
int n = dw.length;
//构建最小堆
for(int i = n/2-1;i >= 0;i--)
{
HeapSort.MinHeapFixDown(dw, i, n);
}
//堆排序
for(int i = n-1;i >=1;i--)
{
swap(dw,0,i); //每次将第n-1,n-2,...1个元素与dw[0]交换后,将最后一个元素从堆中排除
MinHeapFixDown(dw, 0, i); //将每次交换后-1的堆从dw[0]开始,调整为新的最小堆
}
} //交换DataWrap数组中i,j两数值
public static void swap(DataWrap[] dw,int i,int j)
{
DataWrap temp;
temp = dw[i];
dw[i] = dw[j];
dw[j] = temp;
} public static void main(String[] args)
{
DataWrap[] dw = {new DataWrap(25,""),new DataWrap(42,""),new DataWrap(36,""),new DataWrap(8,""),new DataWrap(78,""),new DataWrap(99,"")};
System.out.println("待排序数据为:" + Arrays.toString(dw));
HeapSort.heapSort(dw);
System.out.println("排序后数据为:" + Arrays.toString(dw));
}
}

二、交换排序

1、冒泡排序

  1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。

  2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。

  3.N=N-1,如果N不为0就重复前面二步,否则排序完成。

 public static void bubbleSort(DataWrap[] dw)
{
int n = dw.length;
boolean flag;//设置标志位,若发生未交换的情况,说明已经有序,退出循环即可
for(int i = n-1;i > 0 ;i--)
{
flag = false;
for(int j = 0;j < i;j++)
{
if(dw[j].compareTo(dw[j+1]) > 0)
{
swap(dw,j+1,j);
flag = true;
}
}
if(!flag)
{
break;
}
System.out.println("排序中顺序:" + Arrays.toString(dw));
}
}

2、快速排序

  快速选择排序主要思路是:

  “挖坑填数+分治法”,首先令i =L; j = R; 将a[i]挖出形成第一个坑,称a[i]为基准数。然后j--由后向前找比基准数小的数,找到后挖出此数填入前一个坑a[i]中,再i++由前

向后找比基准数大的数,找到后也挖出此数填到前一个坑a[j]中。重复进行这种“挖坑填数”直到i==j。再将基准数填入a[i]中,这样i之前的数都比基准数小,i之后的数都比基准数

大。因此将数组分成二部分再分别重复上述步骤就完成了排序。

 public class QuickSort
{
public static void quickSort(DataWrap[] dw,int l,int r)
{
if(l < r)
{
int i,j;
DataWrap mid;
i = l;
j = r;
mid = dw[i];
while(i < j)
{
while(i < j && dw[j].compareTo(mid) >= 0)
j--;
if(i < j)
dw[i++] = dw[j];
while(i < j && dw[i].compareTo(mid) <= 0)
i++;
if(i < j)
dw[j--] = dw[i];
}
dw[i] = mid;
quickSort(dw, l, i-1); //递归调用
quickSort(dw, i+1, r);
}
} public static void main(String[] args)
{
DataWrap[] dw =
{
new DataWrap(9, ""),
new DataWrap(-16, ""),
new DataWrap(21, "*"),
new DataWrap(23, ""),
new DataWrap(-30, ""),
new DataWrap(-49, ""),
new DataWrap(21, ""),
new DataWrap(30, "*"),
new DataWrap(13, "*")
};
System.out.println("排序前元素:" + Arrays.toString(dw));
int n = dw.length;
QuickSort.quickSort(dw, 0, n-1);
System.out.println("排序后元素:" + Arrays.toString(dw));
}
}

三、插入排序

1、直接插入排序

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

 public static void directInsertSort(DataWrap[] dw,int n)
{
for(int i = 1;i < n;i++)
{
if(dw[i].compareTo(dw[i-1]) < 0)
{
DataWrap temp = dw[i];
int j;
for(j = i-1;j >= 0 && dw[j].compareTo(temp) > 0;j--)
{
dw[j+1] = dw[j];
}
dw[j+1] = temp;
}
}
}

2、希尔排序(Shell排序、缩小增量排序)

  先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有

序(增量足够小)时,再对全体元素进行一次直接插入排序。由于希尔排序是对相隔若干距离的数据进行直接插入排序,因此可以形象的称希尔排序为“跳着插

     public static void shellSort(DataWrap[] dw)
{
int n = dw.length;
for(int gap = n/2;gap > 0;gap /= 2)
{
for(int i = 0;i < gap;i++)
{
for(int j = i + gap;j < n;j +=gap)
{
if(dw[j-gap].compareTo(dw[j]) > 0)
{
DataWrap temp = dw[j];
int k = j-gap;
while(k >= 0 && dw[k].compareTo(temp) > 0)
{
dw[k+gap] = dw[k];
k -= gap;
}
dw[k+gap] = temp;
}
}
}
}
}

四、归并排序

  当一个数组左边和右边都有序时,将两边合并就完成了排序,而要使两边都有序,则需要用递归。先递归下去,再合并上来,就是归并排序。

 public class MergeSort
{ public static void mergeSort(int[] data)
{
int n = data.length;
sort(data, 0, n-1);//归并排序
} public static void sort(int[] data,int left,int right)
{
if(left <right)
{
int center = (left + right)/2;//中间索引
sort(data, left, center);//堆左边数组进行递归
sort(data, center+1, right);//堆右边数组进行递归
merge(data, left, center, right);//合并
}
} public static void merge(int[] data,int left,int center,int right)
{
int[] array = new int[data.length];//定义临时数组
int mid = center+1;
int k = left;//临时数组索引
int temp = left;
while(left <= center && mid <= right)
{
if(data[left] < data[mid])
array[k++] = data[left++];
else
array[k++] = data[mid++];
}
while(left <= center)
array[k++] = data[left++];
while(mid <= right)
array[k++] = data[mid++];
while(temp <= right)
data[temp] = array[temp++];
} public static void main(String[] args)
{
int[] data = {2,27,56,8,24,12,99,0,56};
MergeSort.mergeSort(data);
for(int i:data)
{
System.out.print(i + ",");
}
}
}

注:本文主要参考:MoreWindows白话经典算法(http://blog.csdn.net/morewindows/article/details/17488865)

          《疯狂Java程序员的基本修养》

经典排序算法(Java实现)的更多相关文章

  1. 一文搞定十大经典排序算法(Java实现)

    本文总结十大经典排序算法及变形,并提供Java实现. 参考文章: 十大经典排序算法总结(Java语言实现) 快速排序算法—左右指针法,挖坑法,前后指针法,递归和非递归 快速排序及优化(三路划分等) 一 ...

  2. 十大经典排序算法最强总结(含JAVA代码实现)(转)

    十大经典排序算法最强总结(含JAVA代码实现)   最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每 ...

  3. Java实现经典七大经典排序算法

    利用Java语言实现七大经典排序算法:冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序. 分类 类别 算法 插入排序类 插入排序.希尔排序 选择排序类 选择排序.堆排序 交换排序类 ...

  4. 十大经典排序算法最强总结(含Java、Python码实现)

    引言 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面 ...

  5. 十大经典排序算法(java实现、配图解,附源码)

    前言: 本文章主要是讲解我个人在学习Java开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...

  6. 经典排序算法之-----选择排序(Java实现)

    其他的经典排序算法链接地址:https://blog.csdn.net/weixin_43304253/article/details/121209905 选择排序思想: 思路: 1.从整个数据中挑选 ...

  7. 七种经典排序算法及Java实现

    排序算法稳定性表示两个值相同的元素在排序前后是否有位置变化.如果前后位置变化,则排序算法是不稳定的,否则是稳定的.稳定性的定义符合常理,两个值相同的元素无需再次交换位置,交换位置是做了一次无用功. 下 ...

  8. java实现经典排序算法

    前言 博主最近在恶补基础知识,算法必然是必不可少的,那么就从经典排序算法开始吧!(图源网络,侵删),没有列出全部,因为在期末考试囧 代码太多,就只显示了最关键的部分 1. 冒泡排序 实现思路: (1) ...

  9. 八大排序算法Java实现

    本文对常见的排序算法进行了总结. 常见排序算法如下: 直接插入排序 希尔排序 简单选择排序 堆排序 冒泡排序 快速排序 归并排序 基数排序 它们都属于内部排序,也就是只考虑数据量较小仅需要使用内存的排 ...

随机推荐

  1. 1041. Be Unique (20)

    Being unique is so important to people on Mars that even their lottery is designed in a unique way. ...

  2. Android小记之--android:listSelector

    使用ListView和GridView时,经常使用android:listSelector来使item被选中时的状态.但如果不配合android:drawSelectorOnTop来使用可能达不到想要 ...

  3. Oracle EBS-SQL (CST-4):检查组织间项目成本.sql

    select       i1.segment1                                                                           项 ...

  4. 使用LINQ来简化编程的7个技巧

    转载地址:http://www.cnblogs.com/lovecherry/archive/2008/05/23/1205565.html 自从学习LINQ以来,我发现了很多使用LINQ来改善代码的 ...

  5. 把自定义控件集成到Qt Designer中

    要想在Qt Designer中使用自定义控件,必须要使Qt Designer能够知道我们的自定义控件的存在.有两种方法可以把新自定义控件的信息通知给Qt Designer:“升级(promotion) ...

  6. HP-UX磁带备份错误收集

    磁带备份命令: make_tape_recovery -Av  默认备份至/dev/rmt/0mn. 如果有多个磁带机,那么需要使用下面命令 make_tape_recovery -Av -a /de ...

  7. wikioi1688 求逆序对

    题目描述 Description 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目 数据范围:N<=105.Ai<=105. ...

  8. ASP.NET-Web-API-Poster.pdf flow chart

    下载地址

  9. 【LeetCode练习题】Unique Paths

    Unique Paths A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagra ...

  10. Error:/bin/bash: /bin/java: No such file or directory

    描述:在Hadoop运行Job的时候,可能会报这样的一个错误“/bin/bash: /bin/java: No such file or directory”,那是因可能有些地方用到了/bin/jav ...