【数据结构】七大排序代码实现

30 篇文章 3 订阅
#include <iostream>
#include <vector>
using namespace std;

/**
 * 遍历并重新初始化
 * @param nums
 */
void display(vector<int>& nums) {
    // 1. 打印数组
    for (int i = 0; i < nums.size(); ++i) {
        cout << nums[i] << " ";
    }
     cout << endl;

    // 2. 重置数组
    nums = {9,8,7,6,5,4,3,1,2};
}

/**
 * 交换数组中两元素的位置
 * @param nums
 * @param i
 * @param j
 */
void swap(vector<int>& nums, int i, int j) {
    // 1. 记录i位置的值
    int tmp = nums[i];
    // 2. 将j位置的值给i位置
    nums[i] = nums[j];
    // 3. 最后将原先保存的i位置的值给j位置
    nums[j] = tmp;
}

/**
 * 插入排序
 * 时间复杂度: n²
 * 稳定性:    稳定
 * @param nums
 */
void insert_sort(vector<int>& nums) {
    for (int i = 1; i < nums.size(); ++i) {
        // 1. 找到当前位置的前一个下标
        int j = i - 1;
        // 2. 记录当前位置的值
        int tmp = nums[i];
        for ( ; j >= 0; j--) {
            // 3. 用选中元素与之前的元素进行比较
            if (nums[j] > tmp) {
                // 4. j位置的值比选中元素的值大,后移一位
                nums[j + 1] = nums[j];
            } else {
                // 5. 此时j位置的值小于当前选中元素结束循环
                break;
            }
        }
        // 6. 将j的后一个元素的值修改为选中的元素
        nums[j + 1] = tmp;
    }
}

/**
 * 希尔排序
 * 时间复杂度: O(n1.2 - 1.5)
 * 稳定性:    不稳定
 * @param nums
 */
void shell_sort (vector<int>& nums) {
    // 1. 定义每次分组的元素个数
    vector<int> gap = {static_cast<int>(nums.size() / 2), 1};
    for (int i = 0; i < gap.size(); i++) {
        // 2. 按照不同的分组元素数进行直接插入排序
        for (int j = gap[i]; j < nums.size(); j++) {
            int k = j - gap[i];
            int tmp = nums[j];
            for ( ; k >= 0; k -= gap[i]) {
                if (nums[k] > tmp) {
                    nums[k + gap[i]] = nums[k];
                } else {
                    break;
                }
            }
            nums[k + gap[i]] = tmp;
        }
    }
}


/**
 * 选择排序
 * 时间复杂度: O(n2)
 * 稳定性:    不稳定
 * @param nums
 */
void select_sort(vector<int>& nums) {
    // 1. 定义左右边界指针
    int left = 0;
    int right = nums.size() - 1;
    // 2. 开始遍历
    while (left < right) {
        // 3. 定义最小值下标与最大值下标
        int min_index = left, max_index = right;

        // 4. 开始寻找最大值与最小值对应的下标
        for (int i = left; i <= right; i++) {
            if (nums[i] < nums[min_index]) {
                min_index = i;
            }

            if (nums[i] > nums[max_index]) {
                max_index = i;
            }
        }

        // 5. 将最小值与左边指针位置进行交换后左指针向右移
        swap(nums,left,min_index);
        if (max_index == left) {
            // 5.1 如果最大值刚好是最左边的元素,由于上述交换最小值时将最左边的最大值换走了,此处需要修改最大值指针
            max_index = min_index;
        }
        // 6. 将最大值与右边指针位置进行交换后右指针左移
        swap(nums,right,max_index);
        right--;
        left++;
    }
}

/**
 * 冒泡排序
 * 时间复杂度: O(n2)
 * 稳定性:    稳定
 * @param nums
 */
void bubble_sort(vector<int>& nums) {
    bool flag = true;
    for (int i = 0; i < nums.size(); i++) {
        for (int j = 0; j < nums.size() - 1 - i; j++) {
            if (nums[j + 1] < nums[j]) {
                flag = false;
                swap(nums, j, j + 1);
            }
        }
        if (flag) break;
    }
}

/**
 * 堆排序
 * 时间复杂度:
 * 稳定性:
 * @param nums
 */
void heap_sort(vector<int>& nums) {
    // 1. 建立大根堆
    for (int parent = (nums.size() - 1 - 1) >> 1; parent >= 0; parent--) {
        // 1.1 找到孩子节点
        int child = (parent << 1)+ 1;
        // 1.2 开始向下调整
        while (child < nums.size()) {
            // 1.3 两个孩子节点中找打最大值
            if (child + 1 < nums.size() && nums[child] < nums[child + 1]) {
                child++;
            }

            // 1.4 如果子节点最大值的值比父节点大则交换,并将父节点指向子节点向下继续调整
            if (nums[child] > nums[parent]) {
                swap(nums, child, parent);

                parent = child;
                child = (parent << 1)+ 1;
            } else {
                // 1.5 如果没有进行了交换则说明已经调整完毕
                break;
            }
        }
    }

    // 2. 交换堆尾与堆顶元素
    int end = nums.size() - 1;
    while (end != 0) {
        // 2.1 将堆顶最大值放在最后
        swap(nums, 0, end);
        // 2.2 此时由于末尾元素在堆顶,导致不是大根堆,于是进行调整为大根堆
        int parent = 0;
        int child = (parent << 1)+ 1;
        while (child < end) {
            if (child + 1 < end && nums[child] < nums[child + 1]) {
                child++;
            }

            if (nums[child] > nums[parent]) {
                swap(nums, child, parent);

                parent = child;
                child = (parent << 1)+ 1;
            } else {
                break;
            }
        }
        // 2.3 将末尾的指针向前调整
        end--;
    }
}

/**
 * 快速排序
 * 时间复杂度: O(n*log(n))
 * 稳定性:    不稳定
 * @param nums
 */
void quick_sort(vector<int>& nums, int left, int right) {
    // 1. 判断递归终止条件
    if (left >= right) {
        return;
    }

    // 2. 找基准    // {9,8,7,6,5,4,3,1,2};
    int start = left, end = right;
    while (start < end) {
        // 2.1 找到右边小于基准的位置
        while (start < end && nums[end] > nums[left]) {
            end--;
        }

        // 2.2 找到左边大于基准的位置
        while (start < end && nums[start] < nums[left]) {
            start++;
        }
        // 2.3 将左右不符合规则(左边都小于基准,右边都大于基准)的位置进行交换
        swap(nums, start, end);
    }
    // 2.4 最后将基准与交叉的指针进行交换
    swap(nums, left, start);

    // 3. 递归
    quick_sort(nums, left, start);
    quick_sort(nums, start + 1, right);
}

/**
 * 归并排序
 * 时间复杂度:O(n*log(n))
 * 稳定性:   稳定
 * @param nums
 */
void merge_sort(vector<int>& nums, int left, int right) {
    // 1. 递归终止条件
    if (left >= right) {
        return;
    }

    // 2. 递归开始
    int mid = (left + right) >> 1;
    merge_sort(nums, left, mid);
    merge_sort(nums, mid + 1, right);

    // 3. 开始合并
    int tmp[nums.size()];
    int s1 = left, s2 = mid + 1, k = 0;
    while (s1 <= mid && s2 <= right) {
        if (nums[s1] > nums[s2]) {
            tmp[k++] = nums[s2++];
        } else {
            tmp[k++] = nums[s1++];
        }
    }

    // 3.1 将剩余未合并的部分进行追加
    while (s1 <= mid) {
        tmp[k++] = nums[s1++];
    }

    while (s2 <= right) {
        tmp[k++] = nums[s2++];
    }

    // 4. 将合并后有序的部分同步到原始数组上
    for (int i = 0; i < k; i++) {
        nums[i + left] = tmp[i];
    }
}

int main() {
    vector<int> nums = {9,8,7,6,5,4,3,1,2};
    // 1. 插入排序
    insert_sort(nums);
    cout << "插入排序:";
    display(nums);

    // 2. 希尔排序
    shell_sort(nums);
    cout << "希尔排序:";
    display(nums);

    // 3. 选择排序
    select_sort(nums);
    cout << "选择排序:";
    display(nums);

    // 4. 冒泡排序
    bubble_sort(nums);
    cout << "冒泡排序:";
    display(nums);

    // 5. 堆排序
    heap_sort(nums);
    cout << "堆排序 :";
    display(nums);

    // 6. 快速排序
    quick_sort(nums, 0, nums.size() - 1);
    cout << "快速排序:";
    display(nums);

    // 7. 归并排序
    merge_sort(nums, 0, nums.size() - 1);
    cout << "归并排序:";
    display(nums);

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1886i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值