以下程序均将数据封装于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. Eddy's research I

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  2. UVA 1599 Ideal Path (HDU 3760)

    两次bfs: 第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路:第二次bfs根据最短距离可以选择满足条件的最短路. 注意!碰到这种很大数据量的题目一定要记得用scanf,printf 输入 ...

  3. File.ReadAllText 读取中文乱码问题

    原文:File.ReadAllText 读取中文乱码问题 用 File.ReadAllText(filepath)   去读取中文txt文件会遇到乱码问题,我自己测试了一下,ANSI编码的txt才会出 ...

  4. hdr_beg(host) 主机名开始

    What does "acl cdn_name hdr_beg(host) -i foor.bar.com" mean in HAProxy's configuration? 在H ...

  5. GetModuleHandle,AfxGetInstanceHandle使用区别

    当一个文件被映射到调用进程的地址空间时,GetModuleHandle函数得到其中某一模块的句柄. 使用GetModuleHandle函数格式:HMODULE GetModuleHandle( LPC ...

  6. 用cssText属性批量操作样式

    给一个HTML元素设置css属性,如 var head= document.getElementById("head"); head.style.width = "200 ...

  7. 【MFC学习笔记-作业8-蝴蝶飞~】【什么鬼作业】

    作业要求: 用定时器控制蝴蝶在窗口废物,如图所示... 这是什么鬼作业啊...蝴蝶还要我这个手残手画啊233333333          (ノಠ .ಠ)ノ彡┻━┻ 不过多亏之前几个鬼作业的福 收获颇 ...

  8. 蜗牛爱课- CGAffineTransformMakeRotation 实现一张图片的自动旋转

    self.locationTimer =[NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector:@selector(tr ...

  9. Twitter License for Android

    1.Apache Software Foundation Apache 软件基金会 2.Apache Thrift 跨平台传输数据,Thrift与其他传输方式的比较:    xml与JSON相比体积太 ...

  10. Weex 开发入门

    去年也听说过 React Native 技术,现在好像很多大公司都在这套技术中踩坑,在开发自己的UI.工作中涉及不到,一直没有学习相关的知识. 并且听说阿里的 vue native,一直很期待.前段时 ...