Sorting algorithm basics + bubble sort + small optimization of bubble sort

Sorting Algorithm

Sorted categories:

1) Internal sorting: refers to loading all the data that needs to be processed into the internal memory ** (memory) ** for sorting.
2) External sorting method: The amount of data is too large to load all of it into the memory, and it needs to be sorted with the help of external storage.

Insert picture description here

time complexity


This method of post-statistics is feasible, but there are two problems: one is to evaluate the performance of the designed algorithm, you need to actually run the program; the other is that the statistics of the time obtained depend on the computer's hardware, software, etc. Environmental factors, in this way, must be run on the same computer in the same state, in order to compare that algorithm faster .

The method of pre-estimation
judges which algorithm is better by analyzing the time complexity of an algorithm.

Time frequency

Time frequency: The time spent by an algorithm is proportional to the number of executions of the statement in the algorithm. The more the number of executions of the statement in the algorithm, the more time it takes. The number of executions of statements in an algorithm is called statement frequency or time frequency. Denoted as T(n).

E.g:

int total = 0;
int end = 100;
//使用for循环计算
for(int i=1;i<=end;i++)			
{
    
    
    total += i;
}
T(n) = n+1;		//n代表程序规模,在这里也就是循环的次数100次 101
//直接计算
total = (1+end)*end/2;
T(n) = 1

in conclusion:

The constant term is generally ignored

2n+20 and 2n as n becomes larger, the execution curve is infinitely close, 20 can be ignored
3n+10 and 3n as n becomes larger, the execution curve is infinitely close, 10 can be ignored

Generally ignore low-order terms

2n 2+3n+10 and 2n 2 As n becomes larger, the execution curve is infinitely close and can be ignored. 3n+10
n 2+5n+20 and n 2 As n becomes larger, the execution curve is infinitely close, and 5n+20 can be ignored.

What about ignoring the coefficient? Generally, the coefficient can be ignored when the frequency of occurrence is too different

Computational time complexity

In general, the number of repeated executions of the basic operation statement in the algorithm is a function of the problem scale n, represented by n). If there is a certain auxiliary function f(n), when n approaches infinity, T The limit value of (m) / f(n) is a constant that is not equal to zero, and f(n) is said to be a function of the same order of magnitude of T(n). Denote it as T(n) = 0(f(n)), and call O(f(n)) the asymptotic time complexity of the algorithm, referred to as time complexity. For example, our above T(n)=n+1, suppose f(n) = n, T(n)/f(n) is infinitely close to 1, then f(n) is the auxiliary function

T(n) is different, but the time complexity may be the same. For example: T(n)=n^2+7n+6 and T(n)3n 2+2n+2 have different T(n), but the time complexity is the same, both are 0(n 2).

Use the constant 1 to replace all the addition constants in the running time T(n)=n^2+7n+6===>T(n) = n^2+7n+1 In the
modified running frequency function, only the highest value is retained Order term T(n)=n^2+7n+1 ===>T(n) = n^2
Remove the coefficient of the highest order term T(n) = n^2 = T(n) = n^2= > O(n) = n^2

Common time complexity

1) Constant order 0(1)
2) Logarithmic order 0(log2n)
3) Linear order 0(n)
4) Linear logarithmic order 0(nlog2n)
5) Square order 0(n^2)
6) Cubic order 0 (n^3)
7) k-th order 0(n^k)
8) Exponential order 0(2^n)

The time complexity of common algorithms from small to large is: 0(1)<0(log2n)<o(n)<o(nlog2n)<0(n 2)<0(n 3))< 0(n^ k) <0(2^n) , as the problem scale n continues to increase, the above-mentioned time complexity continues to increase, and the execution efficiency of the algorithm is lower

So we try to avoid exponential order as much as possible

example

Constant order O(1)

int i = 1; 
int j = 1;
++1;
++j;
int m = i + j;	
上述代码在执行的时候,它消耗的时候并丕随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用0(1)采表示它的时间复杂度。

Logarithmic order 0 (log2n)

int i = 1;
while(i<n){
    
    
    i = i * 2;
}

Explanation: In the while loop, i is multiplied by 2 each time. After the multiplication, i is getting closer and closer to n. Assuming that after the loop x times, i is greater than 2, the loop exits at this time, that is to say, the x power of 2 is equal to n, then x=log2n, that is to say, the code ends after the loop log2n times. Therefore, the time complexity of this code is: O(log2n). The time 2 of O(log2n) changes according to the code, i=i*3, then 0(log;n)

For a simple example, the above code n=1024, how many times does the program execute? Times=log2n

What about n=9, i = i *3? Is the number equal to log3 9 = 2 times, the first time is 1X3, the second time is 3X3

Linear order 0(n)

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

Explanation: This code, the code in the for loop will be executed n times, so the time it consumes varies with the change of n, so this type of code can use 0 (n) to represent its time complexity

Linear logarithmic order 0 (nlog2n)

for(int m=1;m<n;m++){
    
    
   i = 1;
    while(i<n){
    
    
        i = i * 2;
    }
}

Isn’t this just a combination, a while inside for

Square order 0(n^2)

As the name suggests, it is a double for loop

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

By analogy, the other time complexity is revealed one by one

Average time complexity and worst time complexity,

The average time complexity refers to the running time of the algorithm when all possible input instances appear with equal probability.

The worst-case time complexity is called the worst time complexity. The time complexity discussed in general is the worst-case time complexity
. **The reason for this is: **The time complexity in the worst case is the limit of the running time of the algorithm on any input instance, which ensures that the running time of the algorithm will not be longer than the worst case.

Sorting method Average time Worst case stability Extra space Remarks
bubble O (n 2) O (n 2) stable O (1) n hours is better
exchange O (n 2) O (n 2) Unstable O (1) n hours is better
select O (n 2) O (n 2) Unstable O (1) n hours is better
insert O (n 2) O (n 2) stable O (1) Better when most of them are sorted
Base O(log R B) O(log R B) stable O (n) B is a true number (0-9), R is a base (one ten hundred)
Shell O (nlogn) O(n^s ) 1<s<2 Unstable O (1) s is the selected group
fast O (nlogn) O (n ^ 2) Unstable O (nlogn) n is better when large
Merge O (nlogn) O (nlogn) stable O (1) n is better when large
heap O (nlogn) O (nlogn) Unstable O (1) n is better when large

Space complexity

Similar to Wang's theory of time complexity, the space complexity of an algorithm is defined as the storage space consumed by the algorithm, which is also a function of the problem size n.

Space Complexity (Space Complexity) is a measure of the amount of storage space that an algorithm temporarily occupies during its operation. The number of temporary work units that some algorithms need to occupy is related to the scale n of the problem. It increases with the increase of n. When n is larger, it will occupy more storage units, such as quick sort and merge sort algorithms This is the case

When doing algorithm analysis, the main discussion is time complexity. From the user experience point of view, the speed of program execution is more important. Some caching products (redis, memcache) and algorithms (cardinality sorting) essentially use space for time .

Bubble Sort

basic introduction

The basic idea of ​​Bubble Sorting is:

By be sorted sequence from front to back (from the smaller index of the element), comparing the value of adjacent elements sequentially, in reverse order if found then the switch, so that the value of the element is gradually larger toward the rear portion of the past , as water The bubbles underneath gradually rise upwards

What is the reverse order: it is the strategy you set, you let him grow from small to large, the big first is the reverse order

Because each element is constantly approaching its position during the sorting process, if there is no exchange in a comparison, the sequence is in order. Therefore, a flag must be set during the sorting process to determine whether the element has been exchanged. Thereby reducing unnecessary comparisons. It will be optimized later.

Bubble sort diagram

img

rule:

The total number of times to be performed is the size of the array n-1 times

The number of sorts in each pass is gradually decreasing

If there is no exchange in a certain sorting process, we can end the sorting early (optimization)

Code

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/20 21:54
 * @Description TODO
 * @pojectname 冒泡排序
 */
public class BubbleSort {
    
    
    public static void main(String[] args) {
    
    
        //给出我们需要排序的数组
        int[] array = {
    
    3,9,-1,10,-2};
        int temp = 0;//临时变量,交换的时候用
        for (int i = 0; i <array.length-1 ; i++) {
    
    
            for (int j = 0; j < array.length-1-i ; j++) {
    
    
                //如果前面的数比后面数大,交换
            if (array[j] > array[j+1]){
    
    
                temp = array[j];
                array[j] = array[j+1];
                array[j+1] = temp;
             }
            }
            System.out.println("第"+(i+1)+"次排序后的数组");
            System.out.println(Arrays.toString(array));
        }


//        //第一次排序,就是为了把最大的数,排在最后
//        int temp = 0;//临时变量,交换的时候用
//        for (int j=0;j<array.length-1;j++){
    
    
//            //如果前面的数比后面数大,交换
//            if (array[j] > array[j+1]){
    
    
//                temp = array[j];
//                array[j] = array[j+1];
//                array[j+1] = temp;
//            }
//        }
//        System.out.println("第一次排序后的数组");
//        System.out.println(Arrays.toString(array));
//
//        //第二趟排序,把第二大的数排在倒数第二位
//        for (int j=0;j<array.length-1-1;j++){
    
    
//            //如果前面的数比后面数大,交换
//            if (array[j] > array[j+1]){
    
    
//                temp = array[j];
//                array[j] = array[j+1];
//                array[j+1] = temp;
//            }
//        }
//        System.out.println("第二次排序后的数组");
//        System.out.println(Arrays.toString(array));
//
//        //第三趟排序,把第三大的数排在倒数第三位
//        for (int j=0;j<array.length-1-1-1;j++){
    
    
//            //如果前面的数比后面数大,交换
//            if (array[j] > array[j+1]){
    
    
//                temp = array[j];
//                array[j] = array[j+1];
//                array[j+1] = temp;
//            }
//        }
//        System.out.println("第三次排序后的数组");
//        System.out.println(Arrays.toString(array));
//        //第四趟排序,把第三大的数排在倒数第四位
//        for (int j=0;j<array.length-1-3;j++){
    
    
//            //如果前面的数比后面数大,交换
//            if (array[j] > array[j+1]){
    
    
//                temp = array[j];
//                array[j] = array[j+1];
//                array[j+1] = temp;
//            }
//        }
//        System.out.println("第四次排序后的数组");
//        System.out.println(Arrays.toString(array));
    }
}

The comment we made is for understanding. It is not difficult for us to find the rules. The first time we sort it is array.length-1-0, and the second time it is array.lenth-1-1. Since then, it is not difficult for us to find The for loop operation is the same, but the number of loops is different each time, then we can apply a same for loop to the outer layer, and the for loop inside controls the different number of sorts each time

After optimization

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/20 21:54
 * @Description TODO
 * @pojectname 冒泡排序
 */
public class BubbleSort {
    
    
    public static void main(String[] args) {
    
    
        //给出我们需要排序的数组
        int[] array = {
    
    3,9,-1,10,20};
        bubbleSort(array);
        System.out.println("排序后的数组");
        System.out.println(Arrays.toString(array));
    }
    //将前面的排序算法疯转成一个方法
    public static void bubbleSort(int[] array){
    
    
        int temp = 0;//临时变量,交换的时候用
        boolean flag = false;//表示是否进行过交换
        for (int i = 0; i <array.length-1 ; i++) {
    
    
            for (int j = 0; j < array.length-1-i ; j++) {
    
    
                //如果前面的数比后面数大,交换
                if (array[j] > array[j+1]){
    
    
                    flag = true;//说明做出了交换,我不能终止排序
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
            if (flag == false){
    
    //一次循环,没有任何交换
                break;
            }
            else {
    
    
                flag = false;//重置我们的flag,下次交换还得用呢
            }
        }
    }
}

The introduction of our flag is to optimize the number of sorts, some data is special, our flag can end sorting early

What is interesting is that the array is very fast when int[8] is very fast, but it takes more than 20 seconds when int[80000]

Guess you like

Origin blog.csdn.net/qq_22155255/article/details/111464074