Data Structure - Classic Sorting Algorithm: Bubble Sort - Vernacular Detailed Explanation and C/C++ Code Implementation

introduction:

The pioneers who created the sorting algorithm are really admirable, and the design is so ingenious. Today, let’s talk about bubble sorting, which is not only to deepen understanding, but also to share.

Thought:

Bubble sorting is like this, if I currently have an array [x1,x2,x3,...,xn], these n numbers are out of order, then if I want to sort the array, if I want to put the The array is sorted in ascending order. I can determine the specific position of an element xi from front to back (or from back to front) every time. The elements before element xi are smaller than it, and the elements after it are larger than it. Specifically Whether to determine the first positive position or the penultimate first position, just change the loop condition. This may be a bit abstract, so let's give an example to explain the idea of ​​bubble sort step by step:

Declare an array a[7] containing 8 elements, the array subscript starts from 0, so here is the eighth element represented by 7:

2

9

3

4

6

8

7

5

Target:

Sort the array a[8] in ascending order, that is, the small ones are in the front and the big ones are in the back.

Solutions:

First assume that a[i] is the storage location of the minimum element value obtained in my current round, and a[j] and a[j-1] are the current two elements for comparison.

For example, I currently start to traverse the first round, determine a minimum value, and store it in the first position of the array, i=0, that is, the position a[0].

How to determine the minimum value? I start from the last position of the array and traverse forward to make pairwise comparisons, and traverse to the next position of the current minimum storage position. The first round of comparison is specific to my array, a[7] and a[6] Compare once, compare a[6] with a[5] once, compare a[5] with a[4] once, ..., compare a[1] with a[0] once, and perform a[1] and When a[0] is compared, if a[1] is smaller than a[0], then exchange their two positions, otherwise they will not be exchanged. At this time, a[0] stores the minimum value in this round of pairwise comparison; That is, I traverse j=7 to j=1;

Because a[0] has already stored the current minimum value, the minimum value of the next round should be stored in a[1], that is, i=1; the next round starts: I still start from the last position of the array to The previous traversal makes a pairwise comparison, but this round I only traverse a[2] from the back to the front, that is, a[7] is compared with a[6] once, and a[6] is compared with a[5] once , a[5] is compared with a[4] once, ..., a[2] is compared with a[1] once, there is no need to compare a[1] with a[0], because a[0] is already The minimum value of the entire array in the previous round is stored, and now a[1] stores the second minimum value.

next round. . . , for the array I declared, just loop through until i=6, which is also the last round where the length of the array is reduced by 1, because when i=[6], there is only one element i=7 left behind me, this The final position of the two elements can be determined by comparing the two elements once.

Let's demonstrate the idea and remember that the goal is an ascending array:

Element group a[7]:

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

6

8

7

5

(1), when i=0, j=7, a[7]=5, a[6]=7, a[7]<a[6], exchange positions, a[6]=5, a[ 7]=7.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

6

8

5

7

(2), when i=0, j=6, a[6]=5, a[5]=8, a[6]<a[5], exchange positions, a[6]=8, a[ 5]=5.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

6

5

8

7

(3), when i=0, j=5, a[5]=5, a[4]=6, a[5]<a[4], exchange positions, a[5]=6, a[ 4]=5.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

5

6

8

7

(4) When i=0, j=4, a[4]=5, a[3]=4, a[4]>a[3], do not exchange positions.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

5

6

8

7

(5) When i=0, j=3, a[3]=4, a[2]=3, a[3]>a[2], do not exchange positions.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

9

3

4

5

6

8

7

(6), when i=0, j=2, a[2]=3, a[1]=9, a[2]<a[1], exchange positions, a[2]=9, a[ 1]=3.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

3

9

4

5

6

8

7

(7) When i=0, j=1, a[1]=3, a[0]=2, a[2]>a[1], do not exchange positions.

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

2

3

9

4

5

6

8

7

以上就是一轮完整的遍历。接下来就是(i=1,j=7,6,5,4,3,2),(i=2,j=7,6,5,4,3),(i=3,j=7,6,5,4),(i=4,j=7,6,5),(i=5,j=7,6),(i=6,j=7),大家可以手推导加深理解。

第二部分:用数据结构来实现冒泡排序:

  1. 声明一个结构体,结构体中声明一个数组,再声明一个当前数数组长度,其中数组最大存储空间可以用关键字define来定义一个常量。

#include <iostream>
#define MaxSize 10
using namespace std;
typedef struct
{
    int data[MaxSize];
    int length;
}Sqlist;
  1. 由于在遍历数组的过程中需要进行两个数组的交换,所以可以定义一个函数,用于实现数组中的两个数的交换。

void swap(Sqlist *L, int j)
{
    int temp = L->data[j];
    L->data[j] = L->data[j-1];
    L->data[j-1] = temp;
}
  1. 将排序过程单独定义成一个函数,这个函数是实现排序的核心。

void maopao(Sqlist *L)
{
// i是从前往后遍历,遍历到倒数第二个位置
    for(int i=0;i<L->length-1;i++)
    {
// flag用于标志,当前一轮如果没有进行位置交换,说明已经排好序,不需要继续遍历比较,结束函数
        bool flag = false;
// j是从后往前遍历,从最后一个元素开始,比较j和j-1元素的大小,每一轮都遍历到i+1这个位置,因为i之前说的元素都已经有序
        for(int j=L->length-1;j>i;j--)
        {
            if(L->data[j] < L->data[j-1])
            {
// 交换两个元素的位置,调用上面声明的swap函数
                swap(L, j);
                flag=true;
            }
        }
        if(flag==false)
        {
            return;
        }
    }
    return;
}
  1. 主函数用于定义结构体数组中的元素以及长度,然后调用排序函数。

int main()
{
    Sqlist *L;
    L->length=8;
    L->data[0] = 2;
    L->data[1] = 9;
    L->data[2] = 3;
    L->data[3] = 4;
    L->data[4] = 6;
    L->data[5] = 8;
    L->data[6] = 7;
    L->data[7] = 5;
    maopao(L);
    for(int i = 0; i<L->length; i++)
    {
        cout<<"L->data["<<i<<"]="<<L->data[i]<<endl;
    }

    return 0;
}
  1. 运行结果如图所示:

完整代码如下:

#include <iostream>
#define MaxSize 10
using namespace std;
typedef struct
{
    int data[MaxSize];
    int length;
}Sqlist;
void swap(Sqlist *L, int j)
{
    int temp = L->data[j];
    L->data[j] = L->data[j-1];
    L->data[j-1] = temp;
}
void swap1(Sqlist *L, int i, int j)
{
    int temp;
    temp = L->data[i];
    L->data[i] = L->data[j];
    L->data[j] = temp;
}
// 冒泡排序
void maopao(Sqlist *L)
{
    for(int i=0;i<L->length-1;i++)
    {
        bool flag = false;
        for(int j=L->length-1;j>i;j--)
        {
            if(L->data[j] < L->data[j-1])
            {
                swap(L, j);
                flag=true;
            }
        }
        if(flag==false)
        {
            return;
        }
    }
    return;
}
int main()
{
    Sqlist *L;
    L->length=8;
    L->data[0] = 2;
    L->data[1] = 9;
    L->data[2] = 3;
    L->data[3] = 4;
    L->data[4] = 6;
    L->data[5] = 8;
    L->data[6] = 7;
    L->data[7] = 5;
    maopao(L);
    for(int i = 0; i<L->length; i++)
    {
        cout<<"L->data["<<i<<"]="<<L->data[i]<<endl;
    }

    return 0;
}

总结:冒泡排序是一个比较基础的排序,其运行时间复杂度最好为数组有序的情况,比较n-1次即可,最坏为数组反序的情况,比较n(n-1)/2,即时间复杂度为n的平方。

书写不易,谢谢点赞加收藏。

Guess you like

Origin blog.csdn.net/BaoITcore/article/details/129717487