Tipo de bolha
idéias de algoritmo
O princípio da classificação de bolhas é: da esquerda para a direita, os elementos adjacentes são comparados. Cada rodada de comparação, seja a maior ou a menor na sequência, é encontrada. Este número emergirá da extrema direita da sequência.
Tomando a classificação de pequeno para grande como exemplo, após a primeira rodada de comparação, o maior número entre todos os números flutuará para a extrema direita; após a segunda rodada de comparação, o segundo maior número entre todos os números flutuará até o penúltimo posições... basta comparar rodada após rodada e, finalmente, obter a classificação de pequeno para grande.
animação
código do algoritmo
public static void bubbleSort(int[] a){
for (int i = 0; i < a.length-1; i++) {//a.length-1是因为不用与自己比较,所以比的数就少一个
for (int j = 0; j < a.length-1-i; j++){//a.lenght-1-i是因为每一趟就会少一个数比较
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}
O código acima ainda possui algumas deficiências, caso uma sequência já esteja ordenada, ou já esteja ordenada no meio da ordenação. Mas o tipo de bolha ainda passará por dois loops for e a complexidade de tempo é sempre O(n^2) . Por isso, podemos melhorar o código, adicionar um flag antes de cada comparação , se o número for trocado, alterar o flag, indicando que a sequência não está em ordem. Se o sinalizador não mudar após uma comparação, significa que a sequência já está em ordem e não há necessidade de repetir o loop. Neste momento, a complexidade de tempo pode ser melhor alterada para O(n) .
Otimizado
public static void bubbleSort(int[] a){
for (int i = 0; i < a.length-1; i++) {
int flag = 0; //添加标记
for (int j = 0; j < a.length-1-i; j++) {
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
falg++;
}
}
if(flag==0) break; //即falg在经过for循环后,还为0 说明已排好序了,就不用再进行排序
}
}
Análise de Complexidade
Complexidade de tempo O(n^2) Após a otimização, o melhor caso se torna o(n)
teste de complexidade de tempo
Em seguida, vamos tentar testá-lo com muitos dados.
int[] a = new int[10_0000]; //teste de 100.000 dados
1. A função orderArray é implementada para gerar uma sequência ordenada básica, ou seja, organizada do menor para o maior.
public static void orderArray(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
}
2. A função notOrderArray gera uma sequência inversa, ou seja, organizada do maior para o menor.
public static void notOrderArray(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = a.length-i;
}
}
3. A função randomArray gera um array aleatório não ordenado.
public static void randomArray(int[] a) {
Random random = new Random();
for (int i = 0; i < a.length; i++) {
a[i] = random.nextInt(10_0000);
}
}
4. A função testInsertSort testa o valor de retorno de System.currentTimeMillis() em milissegundos.
public static void testInsertSort(int[] a){
int[] tmpArray = Arrays.copyOf(a,a.length);
long startTime = System.currentTimeMillis(); //注意用long接收
shellSort(tmpArray);
long endTime = System.currentTimeMillis(); //返回单位是毫秒
System.out.println("冒泡排序耗时:"+(endTime-startTime));
}
5. Execução da chamada da função principal
public static void main(String[] args) {
int[] a = new int[10_0000];
//有序
System.out.println("基本有序数列");
orderArray(a);
testInsertSort(a);
//倒序
System.out.println("逆序数列");
notOrderArray(a);
testInsertSort(a);
//随机乱序
System.out.println("无序数列");
randomArray(a);
testInsertSort(a);
}
resultado da operação
Por comparação, verifica-se que a complexidade de tempo após a melhoria ainda é reduzida.
código completo
import java.util.Random;
public class sort {
public static void main(String[] args) {
int[] a = new int[10_0000];
//有序
System.out.println("基本有序数列");
orderArray(a);
testInsertSort(a);
//无序
System.out.println("逆序数列");
notOrderArray(a);
testInsertSort(a);
//乱序
System.out.println("无序数列");
randomArray(a);
testInsertSort(a);
}
//冒泡排序
//时间复杂度 O(n^2) 优化后 最好情况 O(n)
public static void bubbleSort(int[] a){
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length-1-i; j++) {
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}
//优化后的冒泡排序
public static void bubbleSort1(int[] a){
for (int i = 0; i < a.length; i++) {
int flag = 0;
for (int j = 0; j < a.length-1-i; j++) {
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
flag++;
}
}
if(flag==0) break;
}
}
//生成有序数组 从小到大排列
public static void orderArray(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
}
//n无序 其实就是从大到小排列
public static void notOrderArray(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = a.length-i;
}
}
//乱序 随机生成序列
public static void randomArray(int[] a) {
Random random = new Random();
for (int i = 0; i < a.length; i++) {
a[i] = random.nextInt(10_0000);
}
}
//大量数据测试
public static void testInsertSort(int[] a){
int[] tmpArray = Arrays.copyOf(a,a.length);
long startTime = System.currentTimeMillis(); //注意用long接收
bubbleSort1(tmpArray);
long endTime = System.currentTimeMillis();
System.out.println("改进冒泡排序耗时:"+(endTime-startTime));
}
}