`
IT求知
  • 浏览: 14982 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

排序算法及java实现

 
阅读更多
import java.util.*;

public class Test {
private static int[] array;

public static void main(String[] args) {
/*
System.out.println("Please enter 10 numbers seperated by space");
Scanner sc = new Scanner(System.in);

for (int i = 0; i < array.length; i++) {
if (sc.hasNext()) {
array[i] = sc.nextInt();
}
}*/

array = new int[]{23,52,11,21,99,1,6,3,91,33,100,23,52,11,21,99,1,6,3,91,33,100,92,85,399,12,1};

//bubbleSort(array);

//selectSort(array);

//insertSort(array);

//shellSort(array);

//directInsertSort(array);

//directInsertSortGuard(array);

mergeSort(array, 0, array.length-1);

//quickSort(array, 0, array.length-1);

for (int i: array) {

System.out.println(i);
}
}

/**
冒泡排序

两两比较,小的往后移动。多次循环,直到有序为止。
比较次数C,移动次数M
最好情况:正序的
比较次数C= n-1
移动次数M= 0
最坏情况:倒序
比较次数C= n*(n-1)/2   第一次比较n次,之后比较n-i次
移动次数M= 3n*(n-1)/2  第一次移动n次,之后移动n-i次,移动一次要移动3次来交换位置。

平均时间复杂度为O(n^2)
稳定排序
*/
private static void bubbleSort(int[] array) {

int temp = 0;
for (int i=0; i<array.length; i++)
for (int j=0; j<array.length-i-1; j++) {
if (array[j] > array[j+1]){
swap(array, j, j+1);
}
}
}

/**
选择排序

从原序列选出最小的放在排序队列第一的位置,然后再从剩余未排序元素中找到最小的,放在排序队列末尾。
依次类推,直到所有元素都有序。
比较次数C,移动次数M
最好情况:正序的
比较次数C= n-1
移动次数M= 0
最坏情况:倒序
比较次数C= n*(n-1)/2   第一次比较n次,之后比较n-i次
移动次数M= 3n*(n-1)/2  第一次移动n次,之后移动n-i次,移动一次要移动3次来交换位置。

平均时间复杂度为O(n^2)
不稳定排序
*/
private static void selectSort(int[] array) {
int temp = 0;
for (int i=0; i<array.length; i++)
for (int j = i+1; j < array.length; j++) {
if (array[i] > array[j]) {
swap(array, i, j);
}
}
}

/**
插入排序

从第一个元素开始,认为该元素已经被排序,取出下一个元素,从后往前与已排序元素比较,插入其中,
并使之有序。重复进行,直到全部都排完。
插入排序包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序)。

最好情况:正序的
比较次数C= n-1
移动次数M= 0
最坏情况:倒序
比较次数C= n*(n-1)/2   第一次比较n次,之后比较n-i次
移动次数M= 3n*(n-1)/2  第一次移动n次,之后移动n-i次,移动一次要移动3次来交换位置。

平均时间复杂度为O(n^2)
稳定排序
*/
private static void insertSort(int[] array) {

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

/**
直接插入排序

算法中引进的附加记录temp称监视哨或哨兵(Sentinel)。
哨兵有两个作用:
带哨兵的插入排序中的哨兵元素有两个作用:
1、暂时存放待插入的元素,使不致于因记录后移而丢失R[i]的内容;
2、它的主要作用是:在查找循环中"监视"下标变量j是否越界。一旦越界(即j=0),因为array[0]与array[j],是和自己比较,
循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(for循环只有一次判断,提高了效率)。
注意:
1、有方法传进来的数组是原始数组,则插入第一个元素时,a[0]会被覆盖,造成最终排完序的数组缺少了原始数组的第一个元素(bug)。
解决方法是:在调用此方法之前,将数组做下处理,使其右移一个元素的位置,空出来的第0个元素初始化为0(或不做初始化)
2、 实际上,一切为简化边界条件而引入的附加结点(元素)均可称为哨兵。
【例】单链表中的头结点实际上是一个哨兵
3、引入哨兵后使得测试查找循环条件的时间大约减少了一半,所以对于记录数较大的文件节约的时间就相当可观。对于类似于
排序这样使用频率非常高的算法,要尽可能地减少其运行时间。所以不能把上述算法中的哨兵视为雕虫小技,而应该深刻理解并掌握这种技巧。

平均时间复杂度为O(n^2)
稳定排序
*/

//无哨兵
private static void directInsertSort(int[] array) {
//直接插入排序,i从第二个开始
for (int i = 1; i < array.length; i++) {
if (array[i] < array[i-1]) {
int temp = array[i];
int j;
for (j = i; j > 0 && temp < array[j-1]; j--) {
array[j] = array[j-1];
}
array[j] = temp;
}
}
}

//有哨兵
private static void directInsertSortGuard(int[] array) {


//用该模式,必需在调用方法之前,将原数组进行处理,所有元素后移一位,空出第一个元素,做array[0]用(哨兵)
//直接插入排序,i从第二个开始
for (int i = 1; i < array.length; i++) {
if (array[i] < array[i-1]) {
array[0] = array[i];
int j;
for (j = i; j > 0 && array[0] < array[j-1]; j--) {
array[j] = array[j-1];
}
array[j] = array[0];
}
}
}


/**
希尔排序

将数据按不同间距,分成几组,然后对每一组进行直接插入排序。刚开始分组,增量大,之后增量越来越小,直到到为1。
希尔排序优于直接插入排序,因为,刚开始增量大时候,分组之后元素少了,再进行直接插入排序所需的移动和比较次数都减少了。
到最后增量小了,元素虽然多,但几乎都有序了,需要移动和比较的次数也少了。

平均时间复杂度为O(n^1.5)
不稳定排序
*/
private static void shellSort(int[] array) {
int d = array.length;
while(true) {
d = d/2;
for (int i = 0; i < d; i++)
//直接插入排序
for (int j = i + d; j < array.length; j += d) {
if (array[j] < array[j-d]){
int temp = array[j];
int k;

for (k = j; k >= d && array[k-d] > temp; k -= d) {
array[k] = array[k-d];
}
array[k] = temp;
}
}


System.out.println("d is " + d);

for (int i: array) {
System.out.println(i);
}


if ( d == 1) {
break;
}
}
}



/*
快速排序

以第一个元素为基准k,遍历一次数据,将所有比k大的放在其后,比k小的放在其前。
将k前和k后的子序列,分别作为初始序列,重复进行刚才的比较。直到子序列为1为止。

平均时间复杂度为O(nlog2n)
不稳定排序
*/
private static void quickSort(int[] array, int start, int end) {
int i = start;
int j = end;
//int tmp = array[i];  //以第一个数为标准,比较大小

if(array == null || array.length == 0) {
return;
}
int n = 0;
while (i < j) {

n++;
if (n >= 10)
return;
System.out.println("i = " + i + "j = " + j + " n " + n);


if (i < j && array[i] <= array[j]) {  // 从后往前找第一个比array[i]小的数,不能忘记“=”情况。
j--;
}
if (i < j) {   // 找出后,交换位置
swap(array, i, j);
}

if (i < j && array[i] < array[j]) {  // 从前往后找,第一个比array[i]大的数
i++;
}
if (i < j) {
swap(array, i, j);   // 找出后,交换位置
}
// 如果i仍然大于j,则继续循环,知道i、j相遇则完成第一次快速排序,
//将大于array[i]的数都放在前面,小于的都放在后面
}

if (i - start > 1) {   // 对前一部分递归进行快速排序
quickSort(array, start, i-1);
}

if (end - i > 1) {     // 对后一部分递归进行快速排序
quickSort(array, i+1, end);
}
}


/*
归并排序

将待排序列从中间一份为二,分成的两部分。前后两部分继续从中间分成两份,直到每个子序列都只剩一个元素为止。
这时候认为各个分好的子序列为有序的,然后将他们按大小顺序合并起来,排好序。


平均时间复杂度为O(nlogn) 需要额外的存储空间。
稳定排序
*/
public static void mergeSort(int[] array, int start, int end) {
if (start < end) {
int mid = (start + end)/2;     // 取开始和结尾的中间位置
mergeSort(array, start, mid);  // 递归进行前一部分归并排序
mergeSort(array, mid+1, end);  // 递归进行后一部分归并排序

// 二路归并
int i = start;
int j = mid + 1;
int k = 0;
int[] temp = new int[end - start + 1];  // 临时数组

// 比较逐一两个子队列,将小的元素放入临时数组中
while (i <= mid && j <= end) {
if (array[i] < array[j]) {
temp[k++] = array[i++];
}
if (array[i] >= array[j]) {
temp[k++] = array[j++];
}
}

// 执行完上一个循环之后,肯定有一个子队列都放入临时数组中
while(i <= mid) {
temp[k++] = array[i++];
}

while(j <= end) {
temp[k++] = array[j++];
}

// 将临时数组中数据,放到原数组中
k = start;
for (int element:temp) {
array[k++] = element;
}
}
}

/*
交换两个数
*/
public static void swap(int[] array, int x, int y) {
int temp = array[x];
array[x] = array[y];
array[y] = temp;
}
}
分享到:
评论

相关推荐

    各种排序算法比较(java实现)

    `Algorithm.java`文件可能包含了这些排序算法的Java实现代码,而`常见排序算法的实现与性能比较.doc`文档则可能详细比较了这些算法的性能和适用场景。`readme.txt`文件可能是对整个项目的简要说明,包括如何运行和...

    Java排序算法实现

    Java排序算法实现 Java排序算法实现 Java排序算法实现

    常用的排序算法(java实现),附带一个PPT动画演示、详解了其中三种

    这里我们主要关注Java实现的排序算法,并结合一个PPT的动画演示来探讨其中的插入排序、直接插入排序和希尔排序。 首先,让我们深入理解插入排序。插入排序是一种简单的排序算法,其基本思想是将未排序的元素逐个...

    各种排序算法java实现

    在提供的文件中,我们可以看到有四种经典的排序算法的Java实现:插入排序、冒泡排序、选择排序以及希尔排序。 **插入排序**: 插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据...

    排序算法的Java实现

    Java作为一种广泛应用的编程语言,提供了丰富的工具来实现各种排序算法。以下将详细解释标题和描述中涉及的几种排序算法的Java实现。 1. **计数排序(RadixSort.java)** 计数排序是一种非基于比较的排序算法,适用...

    常用排序算法的java实现(冒泡、插入、选择、希尔、归并、快排)

    本篇文章将详细讲解标题中提到的六种常见排序算法的Java实现。 1. **冒泡排序**:冒泡排序是最基础的排序算法之一,它通过不断交换相邻的逆序元素来逐渐将较大的元素“浮”到数组的前端。在Java中,冒泡排序的基本...

    8中排序算法(java实现)

    以下是关于标题"8种排序算法(Java实现)"及其描述中提到的排序算法的详细讲解: 1. **插入排序**: - **直接插入排序**:基本思想是从第二个元素开始,逐个与前面已排序的元素比较,找到合适的位置插入,保持已...

    基数排序算法 java实现

    基数排序是一种非比较型整数排序算法,它的原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。这种算法对于大数据量的排序尤其有效,因为其时间复杂度为线性,即O(n*k),其中n是待排序的元素数量,k是每...

    常见的七大排序算法Java实现.zip

    本压缩包"常见的七大排序算法Java实现.zip"包含了七种经典的排序算法在Java语言中的实现。尽管文件列表中并未明确列出每种排序算法的名称,但根据常规,这七大排序算法可能包括冒泡排序、插入排序、选择排序、快速...

    常用排序算法java演示

    本文将深入探讨标题"常用排序算法java演示"中涉及的知识点,包括排序算法的原理、Java实现方式以及其在实际应用中的图形演示。 首先,让我们逐一了解几种常见的排序算法: 1. **冒泡排序(Bubble Sort)**:这是一...

    应用Java和Python实现冒泡排序算法

    冒泡排序:应用Java和Python实现冒泡排序算法 冒泡排序:应用Java和Python实现冒泡排序算法 冒泡排序:应用Java和Python实现冒泡排序算法 冒泡排序:应用Java和Python实现冒泡排序算法 冒泡排序:应用Java和Python...

    八大排序算法总结(含Java实现源代码)

    这里我们将深入探讨八大排序算法,并结合Java语言来理解它们的实现原理。 1. 冒泡排序(Bubble Sort) 冒泡排序是一种简单的交换式排序算法。它通过重复遍历待排序的元素列表,比较相邻元素并根据需要交换它们,...

    各类排序算法java的实现.CHM

    各类排序算法java的实现.CHM 各类排序算法java的实现.CHM

    七大排序算法的java实现

    这里我们将深入探讨七大经典的排序算法,并结合Java语言来理解它们的实现。 1. 插入排序(Insertion Sort) 插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从...

    基于 Java 实现的快速排序算法(java 实现方式)

    【作品名称】:基于 Java 实现的快速排序算法(java 实现方式) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】:基于 ...

    多种排序查找算法java实现

    这个压缩包文件“多种排序查找算法java实现”显然包含了用Java语言编写的多种经典排序和查找算法的源代码。下面,我们将详细讨论这些算法及其在实际应用中的价值。 首先,我们来看排序算法: 1. **选择排序**:这...

    如何使用Java实现归并排序算法,程序详细解读

    归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序算法,程序详细解读; 归并排序:如何使用Java实现归并排序...

Global site tag (gtag.js) - Google Analytics