冒泡排序—数组、数组存储结构的链表排序算法

冒泡排序思想

冒泡排序是一种交换排序,排序过程中两两比较相邻的元素大小,发生逆序则交换,直到没有逆序的元素的为止,每一轮的交换会将的高优先级元素移动到末尾作为已排好序的元素

算法步骤

以实现普通数组从小到大排序为例,对于一个给定的元素序列,每次从第一个元素开始依次遍历,两两比较逆序则交换:

  1. 第1轮遍历,第1个元素与第2个元素比较,逆序则交换,然后继续用第2个元素与第3个元素比较,直到第N-1个元素与第N个元素比较,比较了N-1次确定了最大元素;
  2. 第2轮遍历,同样第1个元素与第2个元素比较,第2个与第3个比较,直到第N-1和第N-2个元素比较,比较了N-2次确定了次大的元素;
  3. 第N-2轮遍历,比较第1个元素和第2个元素,第2个和第3个,比较了2次确定次大元素;
  4. 第N-1轮遍历,比较第1个元素和第2个元素,比较了1次确定最小元素,排序结束

以下图给定的序列为例,各轮排序结果如下:

在这里插入图片描述

算法复杂度

最理想情况:待排序元素已经有序,还是需要比较,但不需要数据交换;

最糟糕情况:待排序元素是逆序的情况下,需要每次比较,而且还要交换数据;

最坏的比较次数,与最坏的交换次数一样都是: ∑ i = 1 n − 1 i = 1 + 2 + 3 + . . . + ( n − 1 ) = n ( n − 1 ) 2 \sum_{i=1}^{n-1} i= 1+2+3+...+(n-1) = \frac{n(n-1)}{2} i=1n1i=1+2+3+...+(n1)=2n(n1)

因此总的时间复杂度为O( n 2 n^2 n2)

数组冒泡排序源码

#include <stdio.h>
#include <stdlib.h>
//数组冒泡排序
void bubbleSort(int arr[], int sz)
{
    int dumy;
    //changed用于检测,当序列已经有序时直接跳出循环
    int changed = 1;
    for (int i = sz - 1; i >= 0 && changed == 1; i--)
    {
        int j = 0;
        changed = 0;
        for (int j = 1; j <= i; j++)
        {
            if (arr[j - 1] > arr[j])
            {
                dumy = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = dumy;
                changed = 1;
            }
        }
    }
}

int output(int arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("%d, ", arr[i]);
    }
    printf("\n");
}

int main()
{
    int arr[] = {6,3,7,4,2,8,5};
    // int arr[] = {2, 5, 6, 7, 1, 4, 8, 9};
    // int arr[] = {1};
    int n = sizeof(arr) / sizeof(int);
    bubbleSort(arr, n);
    output(arr, n);
    return 0;
}
/*
2, 3, 4, 5, 6, 7, 8,
*/

数组存储结构的链表—冒泡排序

采用的也是两两比较,逆序的交换的方法,只是交换的方式有两种方法:

第1种:元素两两比较,交换时不改变指针域,而是直接交换数据域,时间该办法比较方便直接

第2种:交换时数据域不改动,而是通过修改指针域指向来实现数据逻辑顺序的交换,该方法交换时需要记录两个相邻元素各自的前驱指针和后继指针;

例如:需要交换指针B和指针F所指元素,且B的前驱节点的指针为AF的前驱节点的指针为E,此时不仅要交换指针B与指针F,还需要交换其前驱指针A与指针E

该方法实现对元素的1次交换通过对指针域作2次交换来实现,该方法复杂

以上两种方式,时间复杂度均为O( n 2 n^2 n2),以下以第1种方法为例说明:

在这里插入图片描述

数据存储结构的链表—冒泡排序源码

#include <stdio.h>
#include <stdlib.h>

struct Element
{
    //数据域
    int data;
    //指针
    int link;
};

//封装Element相关属性
struct StaticList
{
    int maxSize;
    // elements[0]为附加头节点
    struct Element *elements;
    // tail指针指向最后一个添加的元素,方便尾部插入
    int tail;
    // avail指针指向备用链表的第一个位置
    int avail;
    // 指示当前元素的个数
    int currentSize;
};

//初始化一个基于数据的链表
int initStaticList(struct StaticList *p, int maxSize)
{
    p->avail = 1;
    p->tail = 0;
    p->currentSize = 0;
    p->maxSize = maxSize > 10 ? (maxSize + 1) : 10;
    p->elements = (struct Element *)malloc(p->maxSize * sizeof(struct Element));
    for (int i = 1; i < p->maxSize; i++)
    {
        p->elements[i].link = i + 1;
    }
    p->elements[0].link = -1;
    p->elements[maxSize].link = -1;
}

void addElement(struct StaticList *p, int x)
{
    int cur = p->avail;
    if (cur == -1)
    {
        printf("memory overflow\n");
        return;
    }
    p->avail = p->elements[cur].link;
    p->elements[cur].data = x;
    //新插入元素指针域为-1
    p->elements[cur].link = -1;
    p->elements[p->tail].link = cur;
    p->tail = cur;
    p->currentSize++;
}
void output(struct Element *ems)
{
    int cur = ems[0].link;
    while (cur != -1)
    {
        printf("%d, ", ems[cur].data);
        cur = ems[cur].link;
    }
    printf("\n");
}

//冒泡排序
void bubbleSortElement(struct Element *ems){
    int pos;
    int posnext;
    int endpos = -1;
    int dumy;
    //changed用于检查序列是否发生交换,若没有交换可结束多余的循环
    int changed = 1;
    //head指向第一个有效的元素
    int first = ems[0].link;
    while(endpos!=first && changed==1 ){
        pos = first;
        changed = 0;
        //pos指向当前元素,posnext指向下一个元素
        while(pos!= -1 && ems[pos].link!=endpos){
            posnext = ems[pos].link;
            //发生逆序则交换ems[pos].data与ems[posnext].data
            if(ems[pos].data>ems[posnext].data){
                dumy = ems[pos].data;
                ems[pos].data = ems[posnext].data;
                ems[posnext].data = dumy;
                changed = 1;
            }
            pos = posnext;
        }
        //endpos标记结尾指针,每次更新
        endpos = pos;
    }
}

int main()
{
    struct StaticList p;
    int arr[] = {1, 4, 6, 7, 0, 3, 10, 9, 2, 9,
                 3, 7, 4, 8, 5, 6, 1, 0, 9999, 44,
                 9999, 2, 4, 9, 4, 12, 44, 99, -1, 0,
                 5, 888, 345, 12344, 5555, 9090, 10000, 123, 444, -888,
                 100, 400, 120000, 899999, -1, -2, 8, 9, 8};
    // int arr[]={6,4,3,8,7,5,2,1};
    // int arr[] = {2, 5, 6, 7, 1, 4, 8, 9};
    // int arr[] = {1};
    int n = sizeof(arr) / sizeof(int);
    initStaticList(&p, n);
    for (int i = 0; i < n; i++)
    {
        addElement(&p, arr[i]);
    }
    printf("#### bubble sort before ####\n");
    output(p.elements);
    printf("#### bubble sort after ####\n");
    bubbleSortElement(p.elements);
    output(p.elements);
    free(p.elements);
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值