对于一组,多次将数组中的数两两比较,较大或者较小的数向后排(经过一轮比较后,最大/最小的数就会到结尾),循环直至有序排列。
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
public class maopao {
public static void main(String[] args) {
System.out.println("请输入需要排序的数字,数字之间用空格或者回车隔开,输入完数字后输入任意非数字结束输入");
Scanner scanner = new Scanner(System.in); //复习scanner
Double[] input1= new Double[10]; //复习数组的定义 声明 创建
int count=0;
while (scanner.hasNextDouble()){ //复习scanner.xxx 不用if用while
input1[count] = scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) { //去掉冗余
input2[i]=input1[i];
}
Double[] output = new Double[count];
output=mp(input2);
System.out.println("排序后的数组为:"+Arrays.toString(output));
}
private static Double[] mp(Double[] a) {
double temp;
// 降序排列
for (int i = 0; i < a.length-1; i++) { //n个数分n-1大轮
for (int j = 0; j < a.length-1-i; j++) { //每小轮有n-1-i次排序,每排一大轮每小轮少比较一次(每大轮出一个最值)
if(a[j]
二.选择排序
2.1概述
从第一个数开始,依次和后面的数进行比较,小/大的数往前放(经过一轮最小/大数出现在最前面),之后从第二个数开始上述比较方式,循环至排序结束。
2.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class xuanze {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[100000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count] = scanner.nextDouble();
count++;
}
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i]=input1[i];
}
//System.out.println(Arrays.toString(input2));
Double[] output = new Double[count];
//output=xz(input2);
output=xz1(input2);
System.out.println("排序后的数是:"+Arrays.toString(output));
}
private static Double[] xz(Double[] a) {
double temp;
for (int i = 0; i < a.length-1; i++) {
for (int j = i; j < a.length-1; j++) {
if(a[j]>a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
return a;
}
private static Double[] xz1(Double[] a) {
double temp;
for (int i = 0; i < a.length-1; i++) {
for (int j = i+1; j < a.length; j++) {
if(a[j]
方法xz和方法xz1是两种不同写法。第一中方法是大轮内小轮比较,第二种方法是两两比较。
三.直接插入排序
3.1概述
将数组中第一个数看成一个数组,插入原数组第二个数,使得这两个数形成有序数组,再在这个有序数组插入原数组的第三个数,使得这三个数形成有序数组,以此类推,直到将原数组排序。
3.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class charu {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
Double[] output = new Double[count];
output = cr(input2);
//output=cr1(input2);
//output=cr2(input2);
System.out.println("排序后的数组是:"+ Arrays.toString(output));
}
private static Double[] cr(Double[] a) {
double temp = 0;
for (int i = 0; i < a.length-1; i++) { // i定义大轮数
for (int j = i+1; j >0 ; j--) { // j负责插入数的比较
if (a[j]0&&a[j]0在前
Double temp = a[j];
a[j] = a[j-1];
a[j-1]=temp;
j--;
}
}
return a;
}
private static Double[] cr2(Double[] a) {
for (int i=1;i0 ; j--) {
if (a[j]
四.希尔排序
4.1概述
希尔排序又称缩小增量排序,基本思想是将原数组按增量ht分组,每个子文件安插入法排序。同样,下一个增量ht/2将文件再分为子文件,再按插入法排序。直到ht=1排好序。该方法的关键是是选择合适的增量。
4.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class xier {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
Double[] output = new Double[count];
//output = cr(input2);
output=xe(input2);
System.out.println("排序后的数组为:"+ Arrays.toString(output));
}
private static Double[] xe(Double[] a) {
// //克努特序列
// int jiange = 1;
// while (jiange 0; h=h/2) { //循环h
for (int i = h; i -1 ; j=j-h) { //小轮循环 后面的数与前面的数比较(前后差h)
//j-h大于-1保证索引大于等于0 j=j-h 前后两个数索引位置
if (a[j]
五.快速排序
5.1概述
从数组中取一个数,作为基准数,将比这个数大或者等于的数放到右边,小于的放到左边。(降序),再对左右区间重复上述方法,直到每个区间只有一个数。
5.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class kuaisu {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
//Double[] output = new Double[count];
//output = cr(input2);
ks(input2,0,input2.length-1);
System.out.println("排序后的数组为:"+ Arrays.toString(input2));
}
private static void ks(Double[] a,int start,int end) {
//快速排序法需要利用前后数的位置,默认起始位置为0和length-1
if (start= x) { //从后向前找比选取数小的数
j--;//j一直减,直到找到为止,此时j位置上就是比选取数小的数
}
if (i < j) { //还未找到选取数对应的索引
a[i] = a[j]; //交换数
i++; //下次从前向后找起始,新数下标
}
while (i < j && a[i] <= x) { //向前向后找比比新数大的数
i++; //i一直加,直到找到为止,此时j位置上就是比选取数大的数
}
if (i < j) {
a[j] = a[i]; //交换
j--; //下次从后向前找起始,新数下标
}
}
a[i]=x; //完成一次排序
return i;
//快速排序法 选取一个数经过左小又大的方式(升序)分左右两组,并确定其在数组中的位置;
//再将左右两组分别重复上述方法(递归)再确定两个选取数的位置;
//再次选取、分组、选取、分组......最终确定每个数的位置,完成排序;
//所以ks方法中,有寻找索引和左右分组(前组从前向后,后组从后向前)
//在寻找索引的时候,除了有选取的数,还需要两个数,一个从前向后找位置(前索引),一个从后向前找位置(后索引)
//在两个数不等的时候,先从后找数,直到找到小数后索引一直减,找到后将该数移动到选取数的位置
//再从前找,直到找到大数前索引一直加,找到后将该数移动到后索引的位置
//重复上述,直到前后两索引数相同,定位选取数位置,此时前索引=后索引=选取数的索引
}
}
六.归并排序
6.1概述
假设初始序列有N个数,可以看成是N个有序的子序列,每个子序列长度是1,然后两两归并,得到N/2个长度为2或1的有序子序列,然后两两归并,如此重复直到排序完成。
6.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class guibing {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
//scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
cf(input2,0,input2.length-1);
System.out.println("排序后的数组为:"+ Arrays.toString(input2));
}
private static void cf(Double[] a, int start,int end) {
//先拆分后合并,拆分需要计算从哪分开,需要计算分开位置,所以需要起始和结束位置(start、end)
//计算中间索引
int centerIndex = (start+end)/2;
//开始拆分,分为两组
if (start
七.基数排序
7.1概述
基数排序法基于对不同位的分组(从个位开始)进行排序。
7.2代码实现
import java.util.Arrays;
import java.util.Scanner;
import static sun.management.MemoryUsageCompositeData.getMax;
public class jishu {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
Double[] output = new Double[count];
//output = cr(input2);
output = js(input2);
System.out.println("排序后的数组为:"+ Arrays.toString(output));
}
private static Double[] js(Double[] a) {
double max = getMaxNumber(a); //得到数组中的最大值
int len = String.valueOf(max).length(); //得到最大数一共几位,几位就大循环几次
double[][] temp = new double[10][a.length]; //根据需要创建
int[] c = new int[10]; //c用于计数 c[余数]=有几个某位相同的数 根据需要创建
for (int i = 0,n=1; i < len; i++,n=n*10) { //大循环 n为后加
for (int j = 0; j < a.length; j++) { //将a中的每个数转移出去
int ys = (int) ((a[j] / n) % 10); //丢失精度 该代码比较小数有问题 后加
temp[ys][c[ys]] = a[j]; //赋值 temp[余数][该余数下有多少个数]
c[ys]++;
}
//反转移数
int index=0; //创建反转回的索引
//for (int j = 0; j < a.length; j++) { //错误
for (int k = 0; k < c.length; k++) { //遍历余数(0-9)
if (c[k]!=0){
for (int l = 0; l < c[k]; l++) {//遍历c
a[index]=temp[k][l];
index++;
}}
c[k]=0;
}
//}
//Arrays.fill(c, 0);// 正确
}
return a;
}
private static double getMaxNumber(Double[] a) {
double max = a[0];
for (int i = 0; i < a.length; i++) {
if (a[i]>max){
max = a[i];
}
}
return max;
}
}
//基数排序法不需要两个索引去比较两个数的大小
//需要将数不断按...、十、个位分组排序
八.堆排序
8.1概述
堆排序利用堆这种数据结构进行偶爱徐,堆排序是一种选择性排序。
8.2代码实现
import java.util.Arrays;
import java.util.Scanner;
public class dui {
public static void main(String[] args) {
System.out.println("输入需要排序的数组");
Double[] input1 = new Double[10000000];
int count = 0;
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
input1[count]=scanner.nextDouble();
count++;
}
scanner.close();
Double[] input2 = new Double[count];
for (int i = 0; i < count; i++) {
input2[i] = input1[i];
}
Double[] output = new Double[count];
//output = cr(input2);
output=d(input2);
System.out.println("排序后的数组为:"+ Arrays.toString(output));
}
private static Double[] d(Double[] a) {
//定义开始调整的位置
int start = (a.length-1)/2; //从一半开始调 方便遍历数组全部元素
for (int i = start; i >=0 ; i--) {
toMaxHeap(a,a.length,i); // 将数组变成一个大顶堆
}
for (int i = a.length-1; i >=0 ; i--) { //最后一个数和第一个数交换位置并再次调整大顶堆
double t = a[0];
a[0] = a[i];
a[i] = t;
toMaxHeap(a,i,0);
}
return a;
}
private static void toMaxHeap(Double[] a, int size, int index) {
int left = index*2+1; //左节点
int right = index*2+2;//右节点
int maxIndex = index;
//获取最大节点对应的索引
if(lefta[maxIndex]){
maxIndex=left;
}
if (righta[maxIndex]){
maxIndex=right;
}
//调换位置
if (maxIndex!=index){
double t = a[maxIndex];
a[maxIndex] = a[index];
a[index] = t;
//调换之后可能会影响到下面的子数,不是大顶堆,我们还需要再次调换
toMaxHeap(a,size,maxIndex);
}
}
}
九.总结归纳
时间复杂度和空间复杂度比较
排序方法
时间复杂度
空间复杂度
稳定性
冒泡排序
O(n^2)
O(1)
很好
选择排序
O(n^2)
O(1)
很差
插入排序
O(n^2)
O(1)
很好
希尔排序
介于O(n)和O(n ^ 2)之间
O(1)
较差
快速排序
O(nlogn)
O(logn)
较差
并归排序
O(nlogn)
O(n)
较好
基数排序
O(n+k)
O(n+k)
很不好
堆排序
O(nlogn)
O(1)
较差
其中k是最大元素的值。
更多:8 种常见排序的总结
你可能感兴趣的:(算法,java)