《算法笔记》第4章排序算法

排序算法

1. 冒泡排序

void bubbleSort(int arr[], int n) {
    int flag = 0; //标记本轮是否发生元素交换
    for (int i = 1; i <= n - 1; i++) {
        for (int j = 0; j < n - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = 1;
            }
        }
        if (!flag) break;
    }
}


2. 选择排序

void selectSort(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        int min = i; //标记最小元素的下标
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[min]) {
                min = j;
            }
        }
        int temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;
    }
}


3. 插入排序

void insertSort(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int temp = arr[i], j = i;
        while (j > 0 && temp < arr[j - 1]) { //元素后移
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = temp; //插入到对应的位置
    }
}

4. 归并排序

4.1 二路归并(递归)

const int maxn = 100;
void merge(int A[], int L1, int R1, int L2, int R2) {
    int i = L1, j = L2;        // i指向A[L1],j指向A[L2]
    int temp[maxn], index = 0; // temp临时存放合并后的序列,index为其元素个数
    while (i <= R1 && j <= R2) {
        if (A[i] <= A[j]) {
            temp[index++] = A[i++];
        } else {
            temp[index++] = A[j++];
        }
    }
    while (i <= R1) temp[index++] = A[i++]; //将[L1,R1]中剩余元素直接加入序列C
    while (j <= R2) temp[index++] = A[j++]; //将[L2,R2]中剩余元素直接加入序列C
    for (i = 0; i < index; i++) {
        A[L1 + i] = temp[i]; //将合并后的序列赋值返回序列A
    }
}

void mergeSort(int A[], int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2; //取[left,right]中点
        mergeSort(A, left, mid); //递归,对左子区间[left,mid]归并排序
        mergeSort(A, mid + 1, right); //递归,对右子区间[mid+1,right]归并排序
        merge(A, left, mid, mid + 1, right); //将左子区间和右子区间合并
    }
}

4.2 二路归并(非递归)

const int maxn = 100;
void merge(int A[], int L1, int R1, int L2, int R2) {
    int i = L1, j = L2;        // i指向A[L1],j指向A[L2]
    int temp[maxn], index = 0; // temp临时存放合并后的序列,index为其元素个数
    while (i <= R1 && j <= R2) {
        if (A[i] <= A[j]) {
            temp[index++] = A[i++];
        } else {
            temp[index++] = A[j++];
        }
    }
    while (i <= R1) temp[index++] = A[i++]; //将[L1,R1]中剩余元素直接加入序列C
    while (j <= R2) temp[index++] = A[j++]; //将[L2,R2]中剩余元素直接加入序列C
    for (i = 0; i < index; i++) {
        A[L1 + i] = temp[i]; //将合并后的序列赋值返回序列A
    }
}

void mergeSort(int A[], int n) {
    // step为组内元素个数,step/2为左子区间元素个数
    for (int step = 2; step / 2 <= n; step *= 2) {
        //每step个元素一组,组内前step/2和后step/2个元素进行合并
        for (int i = 0; i < n; i += step) { //对每一组
            int mid = i + step / 2 - 1;
            if (mid + 1 <= n) { //右子区间存在元素则合并,注意最后一个右子区间
                //左子区间为[i,mid],右子区间为[mid+1,min(i+step-1,n)]
                merge(A, i, mid, mid + 1, min(i + step - 1, n));
            }
        }
    }
}

4.3 用sort函数替代merge实现

void mergeSort(int A[], int n) {
    // step为组内元素个数,step/2为左子区间元素个数
    for (int step = 2; step / 2 <= n; step *= 2) {
        //每step个元素一组,组内前step/2和后step/2个元素进行合并
        for (int i = 0; i < n; i += step) { //对每一组
            sort(A + i, A + min(i + step, n + 1));
        }
    }
}


5. 快速排序

5.1 总是以A[left]为主元

//区间划分
int partition(int A[], int left, int right) {
    int temp = A[left]; //以A[left]为主元
    while (left < right) {
        while (left < right && A[right] > temp) right--; //反复左移right
        A[left] = A[right]; //将A[right]移到A[left]
        while (left < right && A[left] < temp) left++; //反复右移left
        A[right] = A[left]; //将A[left]移到A[right]
    }
    A[left] = temp; //把temp放到left和right相遇的地方
    return left; //返回相遇的下标
}
//快速排序
void quickSort(int A[], int left, int right) {
    if (left < right) { //当前区间的长度大于1
        int pos = partition(A, left, right); //划分左右子区间
        quickSort(A, left, pos - 1); //对左子区间递归进行快速排序
        quickSort(A, pos + 1, right); //对右子区间递归进行快速排序
    }
}

5.2 随机主元

int randPartition(int A[], int left, int right) {
    //生成[left,right]内的随机数
    int p = (int)(round(1.0 * rand() / RAND_MAX * (right - left) + left));
    swap(A[p], A[left]); //交换A[p]和A[left]
    int temp = A[left];
    while (left < right) {
        while (left < right && A[right] > temp) right--; //反复左移right
        A[left] = A[right]; //将A[right]移到A[left]
        while (left < right && A[left] < temp) left++; //反复右移left
        A[right] = A[left]; //将A[left]移到A[right]
    }
    A[left] = temp; //把temp放到left和right相遇的地方
    return left; //返回相遇的下标
}

void quickSort(int A[], int left, int right) {
    if (left < right) { //当前区间的长度大于1
        int pos = randPartition(A, left, right); //划分左右子区间
        quickSort(A, left, pos - 1); //对左子区间递归进行快速排序
        quickSort(A, pos + 1, right); //对右子区间递归进行快速排序
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值