C++实现排序算法(简单选择排序、直接插入、冒泡、希尔、快速、堆、折半排序)


算法逻辑可能并不严谨,欢迎各位大佬批评指正!


一、问题分析及数据结构设计

1 问题分析

  1. 输入一组关键字序列,需要实现简单选择排序、直接插入排序和冒泡排序算法。这些排序算法都是基于比较的排序算法,对于给定的关键字序列,通过比较关键字的大小来实现排序。
  2. 对于希尔排序算法,也是一种插入排序算法,但是与直接插入排序不同的是,希尔排序是通过将序列划分为若干个子序列,对每个子序列进行插入排序,然后逐步减小子序列的长度来实现排序。
  3. 快速排序是一种基于比较的排序算法,通过选取一个基准元素,将序列中的元素分为比基准元素小和比基准元素大的两部分,然后递归地对两部分进行排序,最终实现整个序列的排序。
  4. 堆排序是一种基于堆数据结构的排序算法,通过将序列构建成一个最大堆或最小堆,然后不断将堆顶元素与末尾元素交换,并重新调整堆,最终实现整个序列的排序。
  5. 折半插入排序是一种插入排序算法,与直接插入排序不同的是,折半插入排序是通过二分查找找到插入位置,从而减少比较的次数,提高算法的效率。
  6. 最后需要编写一个主函数,设计一个简单的菜单,以便用户能够选择调试上述算法。在菜单中,用户选择要使用的排序算法,最终输出排序结果。

2 数据结构设计

  1. 数组(Array):使用数组来存储关键字序列。数组是一种线性数据结构,通过索引访问元素,用于实现简单选择排序、直接插入排序和冒泡排序等算法。
  2. 链表(Linked List):链表是一种动态数据结构,通过指针将节点连接起来。使用链表来实现希尔排序算法。希尔排序需要分割序列为子序列,链表的插入和删除操作更高效。
  3. 递归或栈(Stack):在实现快速排序算法时,使用递归或栈来处理递归调用。快速排序算法需要逐步划分子序列,通过递归或栈来保存划分的子序列可以有效实现该算法。
  4. 堆(Heap):堆是一种二叉树结构,用于实现堆排序算法。在堆排序中,需要构建一个最大堆或最小堆来实现排序操作。
  5. 二分查找(Binary Search):折半插入排序需要使用二分查找来确定插入的位置。使用有序数组或有序链表来实现折半查找。
  6. 主函数中的菜单使用简单的控制流和用户输入来实现,不需要特定的数据结构。

二、算法设计

1 简单选择排序

1.1 算法思想

算法思想: 每次从待排序的数据元素中选出最小(或最大)的一个元素,存放在起始位置,然后再从剩余未排序元素中继续选择最小(或最大)元素,依次类推,直到所有元素排序完毕。
时间复杂度: O(n^2),其中n为待排序序列的长度。
空间复杂度: O(1)。

1.2 算法流程图

在这里插入图片描述

1.3 算法

// 简单选择排序实现
void simpleSelectionSort(std::vector<int>& arr) {
    for (int i = 0; i < arr.size() - 1; ++i) {
        int minIndex = i;
        for (int j = i + 1; j < arr.size(); ++j) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        std::swap(arr[i], arr[minIndex]);
    }
}

2 直接插入排序

2.1 算法思想

算法思想: 通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
时间复杂度: 最好情况O(n),最坏情况O(n2),平均情况O(n2)。
空间复杂度: O(1)。

2.2 算法流程图

在这里插入图片描述

2.3 算法

// 直接插入排序实现
void directInsertionSort(std::vector<int>& arr) {
    for (int i = 1; i < arr.size(); ++i) {
        int temp = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > temp) {
            arr[j + 1] = arr[j];
            --j;
        }
        arr[j + 1] = temp;
    }
}

3 冒泡排序

3.1 算法思想

算法思想: 比较相邻的元素。如果第一个比第二个大,就交换它们两个;否则就保持不变。对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数。
时间复杂度: 最好情况O(n),最坏情况O(n2),平均情况O(n2)。
空间复杂度: O(1)。

3.2 算法流程图

在这里插入图片描述

3.3 算法

//冒泡排序
void bubbleSort(std::vector<int>& arr) {
    for (int i = 0; i < arr.size() - 1; ++i) {
        for (int j = 0; j < arr.size() - 1 - i; ++j) {
            if (arr[j] > arr[j + 1]) {
                std::swap(arr[j], arr[j + 1]);
            }
        }
    }
}

4 希尔排序

4.1 算法思想

算法思想: 是插入排序的一种更高效的改进版本,先将整个待排序的记录序列分割成为若干子,部分序列分别进行直接插入排序,待整个序列“基本有序”时,再对全体记录进行一次直接插入排序。
时间复杂度: 取决于增量序列的选择,最坏情况达到O(n^2),最好的情况是O(n log^2 n)。
空间复杂度: O(1)。

4.2 算法流程图

在这里插入图片描述

4.3 算法

//希尔排序
void shellSort(std::vector<int>& arr) {
    for (int gap = arr.size() / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < arr.size(); ++i) {
            int temp = arr[i];
            int j = i;
            while (j >= gap && arr[j - gap] > temp) {
                arr[j] = arr[j - gap];
                j -= gap;
            }
            arr[j] = temp;
        }
    }
}

5 快速排序

5.1 算法思想

算法思想: 通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,直到整个序列有序。
时间复杂度: 平均时间复杂度O(n log n),最坏情况O(n^2)。
空间复杂度: 最好情况O(log n),最坏情况O(n)。

5.2 算法流程图

在这里插入图片描述

5.3 算法

//快速排序
void quickSort(std::vector<int>& arr, int left, int right) {
    if (left < right) {
        int pivot = arr[left];
        int low = left;
        int high = right;
        while (low < high) {
            while (low < high && arr[high] >= pivot) {
                --high;
            }
            arr[low] = arr[high];
            while (low < high && arr[low] <= pivot) {
                ++low;
            }
            arr[high] = arr[low];
        }
        arr[low] = pivot;
        quickSort(arr, left, low - 1);
        quickSort(arr, low + 1, right);
    }
}

6 堆排序

6.1 算法思想

算法思想: 将待排序的序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余元素重新调整为大顶堆,再次将根节点与末尾元素交换,反复执行直到整个序列有序。
时间复杂度: O(n log n)。
空间复杂度: O(1)。

6.2 算法流程图

在这里插入图片描述

6.3 算法

//堆排序实现方法
void heapify(std::vector<int>& arr, int n, int i) {
    int largest = i;
    int l = 2 * i + 1;
    int r = 2 * i + 2;
    if (l < n && arr[l] > arr[largest]) {
        largest = l;
    }
    if (r < n && arr[r] > arr[largest]) {
        largest = r;
    }
    if (largest != i) {
        std::swap(arr[i], arr[largest]);
        heapify(arr, n, largest);
    }
}
//堆排序
void heapSort(std::vector<int>& arr) {
    int n = arr.size();
    for (int i = n / 2 - 1; i >= 0; --i) {
        heapify(arr, n, i);
    }
    for (int i = n - 1; i > 0; --i) {
        std::swap(arr[0], arr[i]);
        heapify(arr, i, 0);
    }
}

7 折半插入排序

7.1 算法思想

算法思想: 利用二分查找的思想来减少比较次数,将直接插入排序中的线性查找改为二分查找,从而减少比较的次数
时间复杂度: 最好情况O(n log n),最坏情况O(n^2)。
空间复杂度: O(1)。

7.2 算法流程图

在这里插入图片描述

7.3 算法


//折半插入排序
void binaryInsertionSort(std::vector<int>& arr) {
    for (int i = 1; i < arr.size(); ++i) {
        int temp = arr[i];
        int left = 0;
        int right = i - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < temp) {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        for (int j = i - 1; j >= left; --j) {
            arr[j + 1] = arr[j];
        }
        arr[left] = temp;
    }
}

三、附排序算法完整代码

C++实现排序算法(简单选择排序、直接插入、冒泡、希尔、快速、堆、折半排序))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值