一、插入排序
1.直接插入排序
#include <iostream>
using namespace std;
//直接插入排序
void InsertSort(int A[],int n)
{
int i,j,temp;
for(int i = 1; i< n ; i++)//将各元素插入已排好序的子序列中
{
if(A[i] < A[i-1])//若当前元素小于前一个元素,则交换它们
{
temp = A[i];
for(j = i - 1;j >= 0 && A[j] > temp; --j) //检查所有前面已安排好排序的元素
A[j+1] = A[j]; //所有大于temp的元素都向后挪位
A[j+1] = temp; //插入到插入位置
}
}
}
2.折半插入排序
//折半插入排序
void InsertSort(int A[],int n)
{
int i,j,low,high,mid;
for(i = 2;i<=n;i++) //依次将A[2] ~ A[n]插入前面的已排序序列
{
A[0] = A[i]; //将A[i]暂存到A[0]
low = 1;high = i-1; //设置折半查找的范围
while(low <= high){ //折半查找(默认递增有序)
mid = (low+high)/2; //取中间点
if(A[mid] > A[0]) high = mid -1;//查找左半子表
else low = mid+1; //查找右半子表
}
for(j = i-1;j >= high+1;--i)
A[j+1] = A[j]; //统一后移元素,空出插入位置
A[high+1] = A[0];
}
}
3.希尔排序
//希尔排序
void ShellSort(int A[],int n)
{
//A[0]只是暂存单元,不是哨兵,当j <= 0时,插入位置已到
int d,i,j;
for(d = n/2;d >= 1;d = d/2) //步长变化
for(i = d+1;i <= n;i++)
{
if(A[i] < A[i-d])
{
A[0] = A[i];
for(j = i-d;j > 0&& A[0] < A[j];j -=d)
{
A[j+d] = A[j];
}
A[j+d] = A[0];
}
}
}
二、交换排序
1.冒泡排序
void BubbleSort(int arr[], int n) {
int i,j;
for(i =0;i<n;i++)
{
for(j = 0;j<n-i;j++)
{
if(arr[j] > arr[j+1])
{
swap(arr[j],arr[j+1]);
}
}
}
}
2.快速排序
/用第一个元素将待排序序列划分成左右两个部分
int Partition(int arr[],int low,int high)
{
int pivot = arr[low]; //选取第一个元素作为基准
while(low<high) //用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; //枢轴元素存放到最终位置
return low; //返回枢轴的位置
}
//快速排序
void QuickSort(int arr[],int low,int high)
{
if(low<high) //递归跳出的条件
{
int pivotpos = Partition(arr,low,high); //划分
QuickSort(arr,low,pivotpos-1); //对左子表递归排序
QuickSort(arr,pivotpos+1,high); //对右子表递归排序
}
}
三、选择排序
1.简单选择排序
void selectSort(int arr[], int n) {
for(int i = 0;i<n-1;i++)//一共进行了n-1趟
{
int min = i; //记录最小元素的位置
for(int j = i+1;j<n;j++)
{
if(arr[j] < arr[min])
min = j;
}
if(min != i)//如果最小元素不是当前位置的元素,则交换
{
swap(arr[i],arr[min]);
}
}
}
2.堆排序
//建立大根堆的堆排序
void BuildMaxHeap(int A[],int len);
void HeadAdjust(int A[],int k,int len);
void HeapSort(int A[],int len);
//建立小根堆的堆排序
void BuildMaxHeap1(int A[],int len);
void HeadAdjust1(int A[],int k,int len);
void HeapSort1(int A[],int len);
//建立大根堆
void BuildMaxHeap(int A[],int len)
{
for(int i = len/2;i>0;i--)
HeadAdjust(A,i,len);
}
//将以k为根的子树调整为大根堆
void HeadAdjust(int A[],int k,int len)
{
A[0] = A[k]; //A[0]暂存子树的根节点
for(int i = k*2;i<=len;i *= 2) //沿key较大的子节点向下筛选
{
if(i<len && A[i]<A[i+1])
i++; //选择key较大的子节点
if(A[0]>=A[i])
break;
else
{
A[k] = A[i]; //将A[i]调整到双亲结点上
k = i; //修改k值,以便继续向下筛选
}
}
A[k] = A[0]; //被筛选结点的值放入最终位置
}
//堆排序的完整逻辑
void HeapSort(int A[],int len)
{
BuildMaxHeap(A,len); //初始建堆
for(int i = len;i > 1;i--) //n-1趟的交换和建堆过程
{
swap(A[i],A[1]); //堆顶元素和堆底元素交换
HeadAdjust(A,1,i-1); //把剩余的待排序元素整理成堆
}
}
四、归并排序于基数排序
1.归并排序
//A[low...mid]和A[mid+1...high]各自有序,将两个部分归并
void Merge(int A[],int low,int mid,int high)
{
int i,j,k;
for(k = low;k <= high;k++)
{
B[k] = A[k]; //将A中所有元素复制到B中
}
for(i = low,j = mid + 1,k =i;i <= mid && j <=high;k++)
{
if(B[i] <= B[j]) A[k] = B[i++];
else A[k] = B[j++];
}
while(i <= mid) A[k++] = B[i++];
while(j <= high) A[k++] = B[j++];
}
void MergeSort(int A[],int low,int high)
{
if(low <high)
{
int mid = (low + high) / 2; //从中加划分
MergeSort(A,low,mid); //从左半部分归并排序
MergeSort(A,mid+1,high); //从右半部分归并排序
Merge(A,low,mid,high); //归并两个有序部分
}
}
2.基数排序
// 获取数组中最大的数字
int getMax(vector<int>& arr) {
int max = arr[0];
for (int i = 1; i < arr.size(); i++) {
if (arr[i] > max)
max = arr[i];
}
return max;
}
// 使用计数排序根据位数进行排序
void countSort(vector<int>& arr, int exp) {
int n = arr.size();
vector<int> output(n), count(10, 0);
// 统计每个数字出现的次数
for (int i = 0; i < n; i++)
count[(arr[i] / exp) % 10]++;
// 累加统计数组
for (int i = 1; i < 10; i++)
count[i] += count[i - 1];
// 从原始数组构建输出数组
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
// 将输出数组复制回原始数组
for (int i = 0; i < n; i++)
arr[i] = output[i];
}
// 基数排序函数
void radixSort(vector<int>& arr) {
int max = getMax(arr);
// 对每一位进行计数排序
for (int exp = 1; max / exp > 0; exp *= 10)
countSort(arr, exp);
}
五、外部排序
1.外部排序
2.败者树
3.置换-选择排序
4.最佳归并树