排序算法
1.直接插入排序
每次从无序区间的第一和元素开始,依次与有序区间内的元素从后往前比较 。如果当前有序区间内的元素大于无序区间,则将有序区间该下标元素后移 插入
public static void insertSort(int[] array) {
//有序区间:[0,i)
//无序区间:[i,array.length)
for (int i = 1; i < array.length; i++) {//外层循环找的是无序区间
int k = array[i];//k为无序区间第一个数
int j;//有序区间最后一个数
for (j = i - 1; j >= 0 && array[j] > k; j--) {//遍历的是有序区间
array[j + 1] = array[j];
}//从有序区间的最后一个元素开始比较
// 如果大于无序区间元素 则将有序区间的元素后移 最后插入元素
array[j + 1] = k;//因为最后循环退出的时候j--了 而真正要将无序区间插入的下标在后一个
}
}//直接插入排序
2.希尔排序
希尔排序时直接插入排序的升级版,将数组元素分成(size/2)/((size/3)+1)各组 进行直接插入排序 然后重复上述分组过程 分组 插排
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;//希尔排序的分组数 也可以为gap/2
insertSortWithGapa(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGapa(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {//从第二组请开始依次遍历整个数组
int k = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > k; j -= gap) {//将每一组的元素都与前面几组相对应组的元素比较
array[j + gap] = array[j];
}
array[j+gap] = k;//当循环退出的时候 j的下标减了依次gap
}
}//希尔排序
3.直接选择排序
整个数组看成一个无序区间 每次从无序区间中选择最小(最大) 放入无序区间最前(最后)位置 ,一直到所有元素都排完
- 放在无序区间前面时 无序区间下标为[i,array,length)
- 放在无序区间后面时 无序区间下标为[0,array.length-i)
public static void selectSortSmall(int[] array) {
//无序下标:[i,array.length)
for (int i = 0; i < array.length - 1; i++) {//外层循环 需要循环array.length-1次才可以有序
int j;
int minIndex = i;//设置每次的起始位置为无序序列的第一个位置
for (j = minIndex; j < array.length; j++) { //在无序区间查找最小元素
if (array[j] < array[minIndex])
minIndex = j;
}
swap(array, minIndex, i);
}
}//直接选择排序
//选择无序区间最小的元素放到无序区间第一个位置
public static void selectSortBig(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 无序区间: [0, array.length - i]
int max = 0;
for (int j = 1; j < array.length - i; j++) { //无序区间
if (array[j] > array[max]) {
max = j;
}
}
int t = array[max];
array[max] = array[array.length - i - 1];
array[array.length - i - 1] = t;
}
}//直接选择排序
// 选择无序区间最大的元素放到无序区间最后一个位置
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
4.双向选择排序
直接从无序区间每次选出最大和最小元素 分别放在 无序区间最后和最前位置
特殊情况:当数组中最大元素在第一个位置时 经过与min 交换 当前最大元素下标发生变更 需特殊处理
public static void selectSortOP(int[] array) {
int begin = 0;
int end = array.length - 1;
// [begin,end] 表示整个无序区间
// 当无序区间内只有一个数时停止排序
while (begin <= end) {
int minIndex = begin;
int maxIndex = begin;//无序区间的最大值和最小值 均设置为第一个元素
for (int i = begin + 1; i <= maxIndex; i++) {
if (array[i] < array[minIndex])
minIndex = i;
if (array[i] > array[maxIndex])
maxIndex = i;
}
swap(array, minIndex, begin);
if (maxIndex == begin) {
maxIndex = minIndex;
}
swap(array, maxIndex, end);
begin++;
end--;
}
}//双排
5.堆排序
-
首先对数组进行建堆 建大堆 排升序 建小堆 排降序(我是用大堆 排升序)
-
每次让当前树顶元素与最后一个元素进行交换(每交换一次 当前树内元素减1)
-
对新的树顶进行向下调整
public static void heapSort(int [] array){
createHeap(array);//建大堆
for(int i=0;i<array.length;i++) {
swap(array, 0, array.length-1-i);
//每次让最大的元素与当前树的最后一个节点交换
//在对新的树顶做向下调整 找大的结点
shiftDownBig(array, array.length-i-1, 0);//当前无序期间的结点个数
}
}//堆排序
private static void shiftDownBig(int[] array, int size, int index) {
int left = 2 * index + 1;
while (left < size)
{
int max = left;
int right = left+1;
if (right < size)
{
if (array[right] > array[left])
{
max = right;
}
}
if (array[index] < array[max])
{
swap(array,index,max);
index = max;
left = 2 * index + 1;
}
else
break;
}
}//对指定下标元素做向下调整
private static void createHeap(int[] array) {
for(int j=(array.length-2)/2;j>=0;j--){
shiftDownBig(array,array.length,j);
}
}//建大堆 从最后一个叶子结点的双亲结点开始 依次对其做向下调整
6.冒泡排序
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序
public static void bubbleSort(int []array){
for(int i=0;i<array.length;i++){
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1])
swap(array,j,j+1);//交换
}
}
}//冒泡排序
7.完整代码
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
public class Sort {
public static void insertSort(int[] array) {
//有序区间:[0,i)
//无序区间:[i,array.length)
for (int i = 1; i < array.length; i++) {//外层循环找的是无序区间
int k = array[i];//k为无序区间第一个数
int j;//有序区间最后一个数
for (j = i - 1; j >= 0 && array[j] > k; j--) {//遍历的是有序区间
array[j + 1] = array[j];
}//从有序区间的最后一个元素开始比较
// 如果大于无序区间元素 则将有序区间的元素后移 最后插入元素
array[j + 1] = k;
}
}//直接插入排序
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;//希尔排序的分组数 也可以为gap/2
insertSortWithGapa(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGapa(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {//从第二组请开始依次遍历整个数组
int k = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > k; j -= gap) {//将每一组的元素都与前面几组相对应组的元素比较
array[j + gap] = array[j];
}
array[j+gap] = k;//当循环退出的时候 j的下标减了依次gap
}
}//希尔排序
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static void selectSortSmall(int[] array) {
//无序下标:[i,array.length)
for (int i = 0; i < array.length - 1; i++) {//外层循环 需要循环array.length-1次才可以有序
int j;
int minIndex = i;//设置每次的起始位置为无序序列的第一个位置
for (j = minIndex; j < array.length; j++) { //在无序区间查找最小元素
if (array[j] < array[minIndex])
minIndex = j;
}
swap(array, minIndex, i);
}
}//直接选择排序
//选择无序区间最小的元素放到无序区间第一个位置
public static void selectSortBig(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 无序区间: [0, array.length - i]
int max = 0;
for (int j = 1; j < array.length - i; j++) { //无序区间
if (array[j] > array[max]) {
max = j;
}
}
int t = array[max];
array[max] = array[array.length - i - 1];
array[array.length - i - 1] = t;
}
}//直接选择排序
// 选择无序区间最大的元素放到无序区间最后一个位置
public static void selectSortOP(int[] array) {
int begin = 0;
int end = array.length - 1;
// [begin,end] 表示整个无序区间
// 当无序区间内只有一个数时停止排序
while (begin <= end) {
int minIndex = begin;
int maxIndex = begin;//无序区间的最大值和最小值 均设置为第一个元素
for (int i = begin + 1; i <= maxIndex; i++) {
if (array[i] < array[minIndex])
minIndex = i;
if (array[i] > array[maxIndex])
maxIndex = i;
}
swap(array, minIndex, begin);
if (maxIndex == begin) {
maxIndex = minIndex;
}
swap(array, maxIndex, end);
begin++;
end--;
}
}//双排
public static void heapSort(int [] array){
createHeap(array);//建大堆
for(int i=0;i<array.length;i++) {
swap(array, 0, array.length-1-i);
//每次让最大的元素与当前树的最后一个节点交换
//在对新的树顶做向下调整 找大的结点
shiftDownBig(array, array.length-i-1, 0);//当前无序期间的结点个数
}
}//堆排序
private static void shiftDownBig(int[] array, int size, int index) {
int left = 2 * index + 1;
while (left < size)
{
int max = left;
int right = left+1;
if (right < size)
{
if (array[right] > array[left])
{
max = right;
}
}
if (array[index] < array[max])
{
swap(array,index,max);
index = max;
left = 2 * index + 1;
}
else
break;
}
}//对指定下标元素做向下调整
private static void createHeap(int[] array) {
for(int j=(array.length-2)/2;j>=0;j--){
shiftDownBig(array,array.length,j);
}
}//建大堆 从最后一个叶子结点的双亲结点开始 依次对其做向下调整
public static void bubbleSort(int []array){
for(int i=0;i<array.length;i++){
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1])
swap(array,j,j+1);
}
}
}//冒泡排序
public static void testSpeed() {
Random random = new Random(20190924);
int[] a = new int[10 * 10000];
for (int i = 0; i < 10 * 10000; i++) {
a[i] = random.nextInt(10 * 10000);
}
long begin = System.nanoTime();
heapSort(a);
long end = System.nanoTime();
double ms =(end - begin) * 1.0 / 1000 / 1000;
System.out.printf("一共耗时:%5f毫秒%n", ms);
}
public static void main(String[] args) {
int []a={9,5,2,7,3,6,4,8,4,3,9};
insertSort(a);
System.out.println(Arrays.toString(a));
System.out.println("b*========================");
int []b=a.clone();
bubbleSort(b);
System.out.println(Arrays.toString(b));
System.out.println("c*========================");
int []c=a.clone();
shellSort(c);
System.out.println(Arrays.toString(c));
System.out.println("d*========================");
int []d=a.clone();
heapSort(d);
System.out.println(Arrays.toString(d));
System.out.println("e*========================");
int []e=a.clone();
selectSortBig(e);
System.out.println(Arrays.toString(e));
System.out.println("f*========================");
int []f=a.clone();
selectSortSmall(f);
System.out.println(Arrays.toString(f));
System.out.println("g*========================");
int []g=a.clone();
selectSortOP(g);
System.out.println(Arrays.toString(g));
}
}