#include
#include
using namespace std;
// 冒泡排序
void BubbleSort(vector<int> &nums) {
int len = nums.size();
for (int i = 0; i < len - 1; i++) { // 第i趟
bool exchange = false;
for (int j = 0; j < len - 1 - i; j++) {
if (nums[j] > nums[j+1]) {
swap(nums[j], nums[j+1]);
exchange = true;
}
}
if (!exchange) {
return;
}
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
BubbleSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
// 选择排序
// 主要思想:
// 1、第一层遍历用来记录最小的数应该放的位置
// 2、第二层遍历用来找到最小的数,找打以后和第一层遍历记录下位置的数进行交换
void SelectSort(vector<int>& nums) {
int len = nums.size();
for (int i = 0; i < len - 1; i++) { // 第i趟,走n-1趟
int min_idx = i;
for (int j = i+1; j < len; j++) {
if (nums[j] < nums[min_idx]) { // 找到最小的数
min_idx = j;
}
}
swap(nums[i], nums[min_idx]); // 然后交换
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
SelectSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
// 插入排序
void InsertSort(vector<int>& nums) {
int len = nums.size();
for (int i = 1; i < len; i++) {
int temp = nums[i]; // 保存当前的数
int j = i - 1; // 前一个数的下标
while (j >= 0 && nums[j] > temp) { // 如果前一个数比当前的数大
nums[j + 1] = nums[j]; // 就把前一个数往右移
j -= 1;
}
nums[j + 1] = temp; // 否则就将该数插入带这个位置
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
MergeSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
int partition(vector<int>& nums, int left, int right) {
int temp = nums[left];
while (left < right) {
while (left < right && nums[right] >= temp) { // 如果右边的数大于该数
right--; // 则将指针左移
}
nums[left] = nums[right]; // 否则则交换两边的数
while (left < right && nums[left] <= temp) { // 如果左边的数小于该数
left++; // 则将指针右移
}
nums[right] = nums[left]; // 否则交换两边的数
}
nums[left] = temp; // 将之前暂时保存的数字归位
return left;
}
void QuickSort(vector<int>& nums, int left, int right) {
if (left < right) {
int mid = partition(nums, left, right); // 分隔
QuickSort(nums, left, mid - 1); // 对左边的序列进行排序
QuickSort(nums, mid + 1, right); // 对右边的序列进行排序
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
QuickSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
// 堆排序
/*
1、建立堆(按顺序存储进行存储,然后从最后一个非叶子节点进行调整)
2、得到堆顶元素,为最大元素(大根堆)
3、去掉堆顶,将堆最后一个元素放到堆顶(目的是保持调整完依然是完全二叉树),此时可通过一次调整重新使堆有序
4、堆顶元素为第二大元素
5、重复步骤3,直到堆变空
*/
void sift(vector<int>& nums, int low, int high) { // 调整函数
/*
nums 要排序的数组
low 堆的根节点位置
high 堆的最后一个位置
*/
int i = low; // 指向根节点
int j = 2 * i + 1; // 指向左孩子
int temp = nums[low]; // 暂存根节点的数
while (j <= high) {
if (j + 1 <= high && nums[j + 1] > nums[j]) { // 如果右孩子有且比左孩子大
j = j + 1; // 指向右孩子
}
if (nums[j] > temp) {
nums[i] = nums[j];
i = j; // 往下找一层
j = 2 * i + 1;
}
else {
nums[i] = temp;
break;
}
}
nums[i] = temp;
}
void HeapSort(vector<int> &nums) {
int n = nums.size();
for (int i = (n - 2) / 2; i >= 0; i--) {
// i为建堆的时候调整部分的根的下标
sift(nums, i, n - 1); // 建堆
}
for (int i = n - 1; i >= 0; i--) {
swap(nums[0], nums[i]);
sift(nums, 0, i - 1);
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
HeapSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
// 归并排序(归并的思想同样可以用在合并两个单链表的题目中)
void merge(vector<int>& nums, int low, int mid, int high) {
int i = low; // 用两个索引来遍历两个要合并的序列
int j = mid + 1;
vector<int> ltemp; // 用一个数组暂存要合并的序列
while (i <= mid && j <= high) {
if (nums[i] < nums[j]) { // 对两个有序序列进行遍历排序,有一个序列遍历完结束循环
ltemp.push_back(nums[i]);
i += 1;
}
else {
ltemp.push_back(nums[j]);
j += 1;
}
}
while (i <= mid) { // 将另一个没有遍历完的序列全部插入到temp中
ltemp.push_back(nums[i]);
i += 1;
}
while (j <= high) {
ltemp.push_back(nums[j]);
j += 1;
}
int k = ltemp.size();
for (int i = 0; i < k; i++) {
nums[low++] = ltemp[i]; // 将排序好的序列更新到nums数组中
// 需要注意的一点是,nums的起始索引为low,结束索引为high,不能直接带入0和nums.size()计算!
// 因为这是一个函数,当合并的序列为右边的区间时,nums的起始坐标就不是0了,所以这里更新要使用low和high
}
}
void MergeSort(vector<int> &nums, int low, int high) {
if (low < high) {
int mid = (low + high) / 2;
//对左边的序列进行划分此条命令结束代表左边的序列已经有序(划分到只有一个元素一定是有序的)
MergeSort(nums, low, mid);
//对右边的序列进行划分此条命令结束代表右边的序列已经有序(划分到只有一个元素一定是有序的)
MergeSort(nums, mid + 1, high);
// 合并两个有序序列
merge(nums, low, mid, high);
}
}
int main() {
vector<int> nums = { 2, 4, 5, 7, 1, 3, 6, 8};
int len = nums.size();
MergeSort(nums, 0, len - 1);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
为什么快速排序的效率要比堆排序的效率要高?