ch5 排序

100 阅读2分钟

前提:

  • 输入:待排序数组和元素个数
  • 无输出,一般是从小到大排序
  • 稳定性:任意两个相等的数据,排序前后相对位置不改变
  • 算法无优劣,分情况讨论

image.png

每次交换相邻两元素

image.png

冒泡排序

外层共循环n次,每次归位一个最大的数字;每次交换消去一个逆序对,如果序列基本有序,简单高效

// 冒泡排序
void Bubble(ElementType A[], int N)
{
    for (int i = N - 1; i > 0; i--){
        int flag = 0;
        for (int j = 0; j < i; j++){
            if (A[j] > A[j + 1]){
                Swap(A[j], A[j + 1]);
                flag = 1;//表示发生了交换
            }
        }
        if (flag == 0) break;//全程无交换,数组已经有序
    }
}

直接插入排序

外层共循环n次,每次插入一个数字;每次交换消去一个逆序对,如果序列基本有序,简单高效

// 插入排序
void Insertion(ElementType A[], int N){
    for (int i = 1; i < N; i++){
        int temp = A[i]; // 摸下一张牌
        int j;
        for (j = i; j > 0 && A[j - 1] > temp; j--) // 在已排序序列中从后向前查找插入位置,如果新牌比当前的牌小
            A[j] = A[j - 1];                       // 挪出空位,继续向前比较,直至碰到小于等于新牌的牌
        A[j] = temp;                               // 新牌落位
    }
}

二分插入排序

也是一种插入排序,与直接插入排序不同的是查找插入位置时不是从后向前依次查找,而是使用二分查找的方式,内循环次数减少,在速度上有一定提升

希尔排序

使用类似插入排序的方式,将间隔n个元素的序列进行插入排序,通过不断减小间隔,使序列基本有序,最后1间隔插入排序,得到结果 image.png

image.png

image.png

选择排序

每次在数组未排序的部分中寻找最小值,放到已排序数组的最后,这样循环N次排序就完成了;排序的快慢取决于寻找最小元的快慢

//选择排序
void Selection(ElementType A[], int N){
    for (int i = 0; i < N;i++){
        //从A[i]到A[N-1]中寻找最小元,将值赋给min
        ElementType min = Min(A, i, N - 1);
        //将未排序部分最小元换到有序部分的最后位置
        swap(A[i], A[min]);
    }
}

堆排序

借助最小堆,建造最小堆后每次弹出最小的元素,按照顺序放到临时数组中,最后再复制到原数组中 image.png

image.png

归并排序

image.png

image.png

image.png

image.png

image.png

快速排序

image.png

image.png

image.png

image.png

image.png

表排序

如果待排序元素是很大的结构体,则使用表排序,用一个数组来储存正确元素顺序的下标,而无需频繁移动元素在原数组中的位置 image.png

image.png

image.png

image.png

image.png

image.png

image.png

习题 insert or marge

p124-127