1 冒泡排序
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法
2 插入排序
插入排序算法是基于某序列已经有序排列的情况下,通过一次插入一个元素的方式按照原有排序方式增加元素。这种比较是从该有序序列的最末端开始执行,即要插入序列中的元素最先和有序序列中最大的元素比较,若其大于该最大元素,则可直接插入最大元素的后面即可,否则再向前一位比较查找直至找到应该插入的位置为止。插入排序的基本思想是,每次将1个待排序的记录按其关键字大小插入到前面已经排好序的子序列中,寻找最适当的位置,直至全部记录插入完毕。执行过程中,若遇到和插入元素相等的位置,则将要插人的元素放在该相等元素的后面,因此插入该元素后并未改变原序列的前后顺序。我们认为插入排序也是一种稳定的排序方法。插入排序分直接插入排序、折半插入排序和希尔排序3类。
3 选择排序
选择排序算法的基本思路是为每一个位置选择当前最小的元素。选择排序的基本思想是,基于直接选择排序和堆排序这两种基本的简单排序方法。首先从第1个位置开始对全部元素进行选择,选出全部元素中最小的给该位置,再对第2个位置进行选择,在剩余元素中选择最小的给该位置即可;以此类推,重复进行“最小元素”的选择,直至完成第(n-1)个位置的元素选择,则第n个位置就只剩唯一的最大元素,此时不需再进行选择。使用这种排序时,要注意其中一个不同于冒泡法的细节。举例说明:序列58539.我们知道第一遍选择第1个元素“5”会和元素“3”交换,那么原序列中的两个相同元素“5”之间的前后相对顺序就发生了改变。因此,我们说选择排序不是稳定的排序算法,它在计算过程中会破坏稳定性。
4 快速排序
快速排序的基本思想是:通过一趟排序算法把所需要排序的序列的元素分割成两大块,其中,一部分的元素都要小于或等于另外一部分的序列元素,然后仍根据该种方法对划分后的这两块序列的元素分别再次实行快速排序算法,排序实现的整个过程可以是递归的来进行调用,最终能够实现将所需排序的无序序列元素变为一个有序的序列。
5 时间复杂度比较
算法复杂度介绍参考 https://blog.csdn.net/weixin_40422192/article/details/121662313
6 代码实现
6.1 头文件
#pragma once
#include <iostream>
#include <string>
using namespace std;
#define T int
#define MAXSIZE 20
typedef T SqList[MAXSIZE];
class Sort
{
public:
Sort();
void init(T list[], int n);
void Swap(T &a, T &b);
// 直接插入排序
void InsertSort(int size);
// 带哨兵节点的直接插入排序
void InsertSort_two(int size);
// 折半插入排序
void BInsertSort_two(int size);
// 希尔排序
void ShellSort(int size, int incList[], int listSize);
void ShellInsert(int size, int index);
// 冒泡排序
void BubbleSort(int size);
// 快速排序
void QuickSort(int low, int high);
int Partion(int low, int high);
// 选择排序
void SelectSort(int size);
// 堆排序
T GetMinKey(T heap[], int n);
void ShiftHeap(T heap[], int size, int curPos);
void HeapSort(int size);
void Show(int size);
private:
SqList arr;
};
6.2 cpp文件
#include "Sort.h"
Sort::Sort()
{
for (int i = 0; i < MAXSIZE; i++)
{
arr[i] = 0;
}
}
void Sort::Swap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
void Sort::Show(int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void Sort::init(T list[], int size)
{
for (int i = 0; i < size; i++)
{
arr[i] = list[i];
}
}
void Sort::InsertSort(int size)
{
for (int i = 1; i < size; i++)
{
if (arr[i] < arr[i - 1])
{
Swap(arr[i], arr[i - 1]);
for (int j = i - 1; j > 0 && arr[j] < arr[j - 1]; j--)
{
Swap(arr[j], arr[j - 1]);
}
}
}
}
void Sort::InsertSort_two(int size)
{
for (int i = 2; i < size; i++)
{
if (arr[i] < arr[i - 1])
{
arr[0] = arr[i];
arr[i] = arr[i - 1];
int j = i - 2;
for (; arr[0] < arr[j]; j--)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = arr[0];
}
}
}
void Sort::BInsertSort_two(int size)
{
for (int i = 2; i < size; i++)
{
arr[0] = arr[i];
int low = 1;
int high = i - 1;
while (low <= high)
{
int mid = (low + high) / 2;
if (arr[0] >= arr[mid])
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
for (int j = i; j > high + 1; j--)
{
arr[j] = arr[j - 1];
}
arr[high + 1] = arr[0];
}
}
void Sort::ShellSort(int size, int incList[], int listSize)
{
for (int i = 0; i < listSize; i++)
{
ShellInsert(size, incList[i]);
}
}
void Sort::ShellInsert(int size, int index)
{
for (int i = index + 1; i < size; i++)
{
if (arr[i] < arr[i - index])
{
arr[0] = arr[i];
int j = i - index;
for (; j > 0 && arr[0] < arr[j]; j -= index)
{
arr[j + index] = arr[j];
}
arr[j + index] = arr[0];
}
}
}
void Sort::BubbleSort(int size)
{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
Swap(arr[j], arr[j + 1]);
}
}
}
int Sort::Partion(int low, int high)
{
T key = arr[low];
while (low < high)
{
while (low < high && arr[high] >= key)
high--;
arr[low] = arr[high];
while (low < high && arr[low] < key)
low++;
arr[high] = arr[low];
}
arr[low] = key;
return low;
}
void Sort::QuickSort(int low, int high)
{
if (low < high)
{
int index = Partion(low, high);
QuickSort(low, index - 1);
QuickSort(index + 1, high);
}
}
void Sort::SelectSort(int size)
{
for (int i = 0; i < size - 1; i++)
{
int pos = i;
for (int j = i + 1; j < size; j++)
{
T min = arr[pos];
if (min > arr[j])
{
min = arr[j];
pos = j;
}
}
if (pos != i)
{
Swap(arr[i], arr[pos]);
}
}
}
T Sort::GetMinKey(T heap[], int n)
{
T key = heap[0];
heap[0] = heap[n];
ShiftHeap(heap, n, 0);
return key;
}
void Sort::ShiftHeap(T heap[], int size, int curPos)
{
int i = curPos;
int j = 2 * i + 1; // left node
while (j < size)
{
if (j < size - 1 && heap[j] > heap[j + 1])
j++; // ensure j point to min node
if (heap[i] <= heap[j])
break;
else
{
Swap(heap[i], heap[j]);
i = j;
j = 2 * i + 1;
}
}
}
void Sort::HeapSort(int size)
{
T* heap = new T[size];
for (int i = 0; i < size; i++)
{
heap[i] = arr[i];
}
int curPos = size / 2 - 1;
while (curPos >= 0)
{
ShiftHeap(heap, size, curPos);
curPos--;
}
for (int i = 0; i < size; i++)
{
arr[i] = GetMinKey(heap, size - i - 1);
}
delete[] heap;
}
6.3 测试文件
#include "Sort.h"
int main()
{
int arr[] = {278,109,63,930,589,184,505,269,8,83};
int size = sizeof(arr) / sizeof(arr[0]);
Sort s;
s.init(arr , size);
s.Show(size);
int incList[] = { 5, 3, 2, 1};
int listSize = sizeof(incList) / sizeof(incList[0]);
//s.ShellSort(size, incList, listSize);
//s.InsertSort(size);
//s.InsertSort_two(size);
//s.BInsertSort_two(size);
// s.BubbleSort(size);
//s.SelectSort(size);
//int low = 0;
//int high = size - 1;
//s.QuickSort(low, high);
s.HeapSort(size);
s.Show(size);
return 0;
}