冒泡排序

public class MaoPaoSort {

public static void main(String[] args) {

int[] a = { 28, -30, 25, 70, 6,2,3,4,5,6,234,-234 };



         // 外层for循环控制循环次数

for(int j = 1;j <= a.length - 1;j++){//冒泡排序

// 内层for循环控制相邻的两个元素进行比较

    for (int i = 0; i < a.length - j; i++) {

if (a[i] > a[i + 1]) {

int temp = a[i];

a[i] = a[i + 1];

a[i + 1] = temp;

}

}

}

 

for (int i = 0; i < a.length; i++) {

System.out.print(a[i] + " ");

}

}

}

        

 

直接选择排序

public class DirectSelectSort {

 public static void sort(int[] array) {

//将数组的长度赋给len是为了防止每次for循环中判断时都调用length方法影响性能

        int len = array.length;

 

        for (int i = 0; i < len - 1; i++) {

 

            int min = i;// 设当前第i条记录为最小值

 

            // 找出(i+1)到(len-1)中最小值的下标

            for (int j = i + 1; j < len; j++) {

                if (array[j] < array[min]) {

                    min = j;// 记录最小值下标

                }

            }

 

            // 将最小值记录与第i条记录交换

            if (min != i) {

                int temp = array[i];

                array[i] = array[min];

                array[min] = temp;

            }

        }

    }

 

    public static void main(String [] args){

        int [] array = {45,89,699,52,14,236,58,7};

        sort(array);

        System.out.println(Arrays.toString(array));

    }

}

直接插入排序

public class InsertSort {

public static void getInsertSort(int[] a) {

        if(a == null || a.length == 0) {//判断数组是否为空

            System.out.println("该数组为空!");

            return;

        }

        int n = a.length;//将数组的长度赋给n是为了防止每次for循环中判断时都调用length方法影响性能

        int temp;//放于for循环外面是为了防止重复创建变量

        int j;

        for(int i = 1; i < n;i++){//排序的趟数

            temp = a[i];//赋给temp是为了防止索引i之前的元素向后移动覆盖了索引i的元素

            j = i-1;

            for(j=i-1; j>=0&&a[j]>temp; --j) {//将大于i位置元素的元素向后移

                a[j+1] = a[j];

            }

            a[j+1]= temp;//找到i应该在的位置,将值放置此处

        }

    }

    public static void main(String[] args) {

        int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};

        getInsertSort(a);

              for(int i = 0; i < a.length; i++) {

            System.out.print(a[i] + " ");

        }

    }

}

 

 

 

归并排序

归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取。

工作原理:

1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

2、设定两个指针,最初位置分别为两个已经排序序列的起始位置

3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

4、重复步骤3直到某一指针达到序列尾

5、将另一序列剩下的所有元素直接复制到合并序列尾

 

package test;

import java.util.Arrays;

public class MergeSort {

/**

 * 归并排序

 * 简介:将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列

 * 时间复杂度为O(nlogn)

 * 稳定排序方式

 * @param nums 待排序数组

 * @return 输出有序数组

 */

public static int[] sort(int[] nums, int low, int high) {

int mid = (low + high) / 2;

if (low < high) {

// 对左边数组进行递归

sort(nums, low, mid);

// 对右边数组进行递归

sort(nums, mid + 1, high);

// 左右归并

merge(nums, low, mid, high);

}

return nums;

}

 

public static void merge(int[] nums, int low, int mid, int high) {

int[] temp = new int[high - low + 1];//定义新数组长度

int i = low;// 左指针

int j = mid + 1;// 右指针

int k = 0;

 

// 把较小的数先移到新数组中

while (i <= mid && j <= high) {

if (nums[i] < nums[j]) {

temp[k++] = nums[i++];//取出最小值放入左边的数组

} else {

temp[k++] = nums[j++];//取出最小值放入右边的数组

}

}

 

// 把左边剩余的数移入数组

while (i <= mid) {

temp[k++] = nums[i++];

}

 

// 把右边边剩余的数移入数组

while (j <= high) {

temp[k++] = nums[j++];

}

 

// 把新数组中的数覆盖nums数组

for (int k2 = 0; k2 < temp.length; k2++) {

nums[k2 + low] = temp[k2];

}

}

 

 

// 归并排序的实现

public static void main(String[] args) {

 

int[] nums = { 2, 7, 8, 3, 1, 6, 9, 0, 5, 4 };

 

MergeSort.sort(nums, 0, nums.length-1);

System.out.println(Arrays.toString(nums));

}

}

 

 

快速排序

快速排序,顾名思义,是一种速度快,效率高的排序算法。

快排原理:

        在要排的数(比如数组A)中选择一个中心值key(比如A[0]),通过一趟排序将数组A分成两部分,其中以key为中心,key右边都比key大,key左边的都key小,然后对这两部分分别重复这个过程,直到整个有序。

        整个快排的过程就简化为了一趟排序的过程,然后递归调用就行了。

        一趟排序的方法:

1,定义i=0,j=A.lenght-1,i为第一个数的下标,j为最后一个数下标

2,从数组的最后一个数Aj从右往左找,找到第一小于key的数,记为Aj;

3,从数组的第一个数Ai 从左往右找,找到第一个大于key的数,记为Ai;

4,交换Ai 和Aj 

5,重复这个过程,直到 i=j

6,调整key的位置,把A[i] 和key交换

假设要排的数组为:A[8] ={ 5 2 8 9 2 3 4 9 }

           选择 key = 5, 开始时 i=0,j=7

  index       0    1    2    3    4    5    6    7

开始:          2    8    9    2    3    4    9

                  i                                         j  

第一次找   5    2    8    9    2    3    4    9

                              i                       j

交换:       5    2    4    9    2    3    8    9 

                              i                       j

第二次找   5    2    4    9    2    3    8    9

                                    i           j

交换:       5    2    4    3    2    9    8    9

                                    i            j

第三次找    5    2    4    3    2    9    8    9

                                          ij   

调整key:    5    4    3    5    9    8    9

                                           ij

 

package test;

import java.util.Arrays;

 public class QuickSort {

public static void main(String[] args) {

int[] a = {1, 2, 4, 5, 7, 4, 5 ,3 ,9 ,0,88,55};

/*另一种输出方式

quickSort(a,0,a.length-1);

for (int i = 0; i < a.length; i++) {

System.out.print(a[i]+" ");

}*/

  quickSort(a);

  System.out.println(Arrays.toString(a));

}

public static void quickSort(int[] a) {

if(a.length>0) {

quickSort(a, 0 , a.length-1);

}

} 

private static void quickSort(int[] a, int low, int high) {

//1,找到递归算法的出口

if( low > high) {

return;

}

//2, 存

int i = low;

int j = high;

//3,key

int key = a[ low ];

//4,完成一趟排序

while( i< j) {

//4.1 ,从右往左找到第一个小于key的数

while(i<j && a[j] > key){

j--;

}

// 4.2 从左往右找到第一个大于key的数

while( i<j && a[i] <= key) {

i++;

}

//4.3 交换

if(i<j) {

int p = a[i];

a[i] = a[j];

a[j] = p;

}

}

// 4.4,调整key的位置

int p = a[i];

a[i] = a[low];

a[low] = p;

//5, 对key左边的数快排

quickSort(a, low, i-1 );

//6, 对key右边的数快排

quickSort(a, i+1, high);

}

}

 

 

 

希尔排序

希尔排序(缩小增量法) 属于插入类排序,由Shell提出,希尔排序对直接插入排序进行了简单的改进:它通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项大跨度地移动,当这些数据项排过一趟序之后,希尔排序算法减小数据项的间隔再进行排序,依次进行下去,进行这些排序时的数据项之间的间隔被称为增量,习惯上用字母h来表示这个增量。

常用的h序列由Knuth提出,该序列从1开始,通过如下公式产生:

h = 3 * h +1

反过来程序需要反向计算h序列,应该使用

h=(h-1)/3

 

package paixu;

import java.util.Arrays;

public class ShellSortTest {

public static void main(String[] args) {

int[] data = new int[] { 52, 13, 6, 22, 1, 9, 4, 8, 7,66,54 };

shellSort(data);

System.out.println(Arrays.toString(data));

}

public static void shellSort(int[] data) {

// 计算出最大的h值

int h = 1;

while (h <= data.length / 3) {

h = h * 3 + 1;

}

while (h > 0) {

for (int i = h; i < data.length; i += h) {

if (data[i] < data[i - h]) {

int tmp = data[i];

int j = i - h;

while (j >= 0 && data[j] > tmp) {

data[j + h] = data[j];

j -= h;

}

data[j + h] = tmp;

}

}

// 计算出下一个h值

h = (h - 1) / 3;

}

}

}

 

 

堆排序

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。(摘自百度百科)

 

想知道什么是堆排序,就得先知道什么是堆,堆分为两种,大根堆和小根堆,什么是大根堆小根堆呢?那你得先知道完全二叉树,什么是完全二叉树?完全二叉树,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。要是问什么是二叉树(自己去百度吧……),把完全二叉树理解了之后,就可以看大根堆小根堆了,大根堆的要求是每个节点的值都不大于其父节点的值,小根堆则相反,所以说,如果我构造出来一个大根堆,那么最上面的根节点一定是最大的

 

堆排序的原理就是这样,先构造出来大根堆(假设从小到大排序),然后取出堆顶元素(也就是最大的元素),放到数组的最后面,然后再将剩余的元素构造大根堆,再取出堆顶元素放到数组倒数第二个位置,依次类推,知道所有的元素都放到数组中,排序就完成了,仔细看代码吧,光看字是很难懂的

 

下面是Java代码实现:

public class HeapSortTest {

public static void main(String[] args)

    {

        //定义整型数组

        int[] arr = {1,25,6,8,47,22,3,4,9,0};

        //调用堆排序数组

        HeapSort(arr);

        //输出排序后的数组

        System.out.println(Arrays.toString(arr));

    }

    //堆排序函数

    public static void HeapSort(int[] arr)

    {

        int n = arr.length-1;

        for(int i=(n-1)/2;i>=0;i--)

        {

            //构造大顶堆,从下往上构造

            //i为最后一个根节点,n为数组最后一个元素的下标

            HeapAdjust(arr,i,n);

        }

        for(int i=n;i>0;i--)

        {

            //把最大的数,也就是顶放到最后

            //i每次减一,因为要放的位置每次都不是固定的

            swap(arr,i);

            //再构造大顶堆

            HeapAdjust(arr,0,i-1);

        }

    }

 

    //构造大顶堆函数,parent为父节点,last为数组最后一个元素的下标

    public static void HeapAdjust(int[] arr,int parent,int last)

    {

        //定义临时变量存储父节点中的数据,防止被覆盖

        int temp = arr[parent];

        //2*parent+1是其左孩子节点

        for(int i=parent*2+1;i<=last;i=i*2+1)

        {

            //如果左孩子大于右孩子,就让i指向右孩子

            if(i<last && arr[i]<arr[i+1])

            {

                i++;

            }

            //如果父节点大于或者等于较大的孩子,那就退出循环

            if(temp>=arr[i])

            {

                break;

            }

            //如果父节点小于孩子节点,那就把孩子节点放到父节点上

            arr[parent] = arr[i];

            //把孩子节点的下标赋值给parent

            //让其继续循环以保证大根堆构造正确

            parent = i;

        }

        //将刚刚的父节点中的数据赋值给新位置

        arr[parent] = temp;

    }

 

    //定义swap函数

    //功能:将根元素与最后位置的元素交换

    //注意这里的最后是相对最后,是在变化的

    public static void swap(int[] arr,int i)

    {

        int temp = arr[0];

        arr[0] = arr[i];

        arr[i] = temp;

    }

}

10-07 10:58