今天用c++把常见的排序算法实现了一遍。
class Sort
{
void swap(int& a, int& b)
{
if (a == b)
return;
a ^= b;
b ^= a;
a ^= b;
}
//调整堆,根节点的左右两个子树都是调整好的大根堆,只需要把根节点与左右子树的根节点比较
//找出最大值,把最大值往上提,小值往下沉,就可以调整好堆
void MaxHeapify(int a[], int maxIndex, int n)
{
int largest = maxIndex;
int left = maxIndex * 2 + 1;
int right = maxIndex * 2 + 2;
if (left < n && a[left] > a[maxIndex])
{
largest = left;
}
if (right < n && a[right] > a[largest])
{
largest = right;
}
if (largest != maxIndex)
{
swap(a[largest], a[maxIndex]);
MaxHeapify(a, largest, n);
}
}
//创建初始堆
void BuildMaxHeap(int a[], int n)
{
//完全二叉树最后一个非叶子节点下标为n/2-1
for (int i = n / 2 - 1; i >= 0; i--)
{
MaxHeapify(a, i, n);
}
}
void merge(int a[], int low, int mid, int hight)
{
if (low == hight)
return;
merge(a, low, (mid - low) / 2 + low, mid);
merge(a, mid + 1, (hight - mid - 1) / 2 + mid + 1, hight);
int* tmp = new int[hight - low + 1];
int* p = tmp;
int i = low;
int j = mid + 1;
while (i <= mid && j <= hight)
{
if (a[i] <= a[j])
{
*p++ = a[i++];
}
else
{
*p++ = a[j++];
}
}
while (i <= mid)
{
*p++ = a[i++];
}
while (j <= hight)
{
*p++ = a[j++];
}
for (int i = 0; i < hight - low + 1; i++)
{
a[low + i] = *(tmp + i);
}
delete[] tmp;
}
public:
//直接插入排序
void insert_sort(int* a, int n)
{
for (int i = 0; i < n; i++)
{
int j = i;
while (j > 0)
{
if (a[j] >= a[j - 1])
break;
swap(a[j], a[j - 1]);
j--;
}
}
}
//希尔排序,插入排序的变种
void shell_sort(int* a, int n)
{
int m = n;
while (m /= 2)
{
for (int i = m; i < n; i++)
{
int j = i;
while (j > 0)
{
if (a[j] >= a[j - m])
break;
swap(a[j], a[j - m]);
j -= m;
}
}
}
}
//冒泡排序
void bubble_sort(int a[], int n)
{
bool isSort = true;
for (int i = 0; i < n; i++)
{
isSort = true;
for (int j = n - 1; j > i; j--)
{
if (a[j] >= a[j - 1])
continue;
swap(a[j], a[j - 1]);
isSort = false; //如果发生交换则表明还没有排好序,如果没有发生交换说明已经排好序了
}
if (isSort)
return;
}
}
//快速排序
void quick_sort(int a[], int n)
{
int* low = a;
int* hight = a + n - 1;
int* bp = low; //默认使用第一个数做基准数据
int* tp = hight;
if (low == hight)
return;
//快排的主要思路就是,对每一次递归的子数组进行遍历,比较每个数与基准数的大小
//小于基准数的放在基准数的左边,大于基准数的放在右边
//所以关键是每次遍历数组的方法,这里每次递归选择数组的第一个数为基准数,从数组末尾往回遍历数组
//tp为遍历数组的指针,bp为基准数指针
while (tp != low)
{
if (tp > bp)
{
if (*tp >= *bp)
{
tp--;
}
else
{
swap(*bp, *tp);
bp = tp;
tp--;
}
}
else
{
if (*tp <= *bp)
{
tp--;
}
else
{
swap(*bp, *tp);
bp = tp;
tp--;
}
}
}
if(low + 1 < bp)
quick_sort(low, bp - low + 1);
if(bp + 1 < hight)
quick_sort(bp + 1, hight - bp);
}
//直接选择排序
void select_sort(int a[], int n)
{
for (int i = 0; i < n; i++)
{
int* min = a + i;
for (int j = i + 1; j < n; j++)
{
if (a[j] < *min)
{
min = a + j;
}
}
swap(a[i], *min);
}
}
//堆排序有三步,1、从最后一个非叶子节点开始往回调整堆,创建初始堆;2、将堆顶的最大数与未排序区末尾的数互换;3、重新调整未排序区
void heap_sort(int a[], int n)
{
BuildMaxHeap(a, n);
for (int i = 1; i < n; i++)
{
swap(a[0], a[n - i]);
MaxHeapify(a, 0, n - i);
}
}
//归并排序
void merge_sort(int a[], int n)
{
merge(a, 0, n / 2 - 1, n-1);
}
};