数据结构–排序模板(C语言)
1.插入排序–直接插入排序(稳定的排序算法)
//折半插入排序--稳定排序。
//时间复杂度:最好情况下:O(n)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void InsertSort3(int* A,int numSize){
int i,j,low,high,mid,temp;
for(int i=1;i<numSize;i++){
//找到前有序序列的当前数的插入位置
temp=A[i];
low=0,high=i-1;
while(low<=high){
mid=(low+high)/2;
if(A[mid]>temp){
high=mid-1;
}else{
low=mid+1;
}
}
//插入
for(int j=i-1;j>=high+1;j--){
A[j+1]=A[j];
}
A[high+1]=temp;
}
}
//插入排序2--稳定排序。
//时间复杂度:最好情况下:O(n)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void InsertSort2(int* A,int numSize){
for(int i=1;i<numSize;i++){
//找到位置后再插入
int temp=A[i];
int j=i;
while(j-1>=0&&temp<A[j-1]){
A[j]=A[j-1];
j-=1;
}
if(j!=i){
A[j]=temp;
}
}
}
//插入排序1--稳定排序。
//时间复杂度:最好情况下:O(n)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void InsertSort(int* A,int numSize){
for(int i=1;i<numSize;i++){
for(int j=i-1;j>=0;j--){
if(A[j]>A[j+1]){//交换
A[j+1]=A[j+1]^A[j];
A[j]=A[j+1]^A[j];
A[j+1]=A[j+1]^A[j];
}
}
}
}
2.插入排序–希尔排序(不稳定的排序算法)
//希尔排序优化。
//时间复杂度:最好情况下:O(n^1.3)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void XierSort(int* A,int numSize){
for(int d=numSize/2;d>0;d/=2){//取步长
for(int i=d;i<numSize;i++){//遍历步长
//交换法
for(int j=i-d;j>=0;j-=d){
if(A[j+d]<A[j]){
A[j+d]=A[j+d]^A[j];
A[j]=A[j+d]^A[j];
A[j+d]=A[j+d]^A[j];
}
}
}
}
}
//希尔排序优化。
//时间复杂度:最好情况下:O(n^1.3)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void XierSort2(int* A,int numSize){
for(int d=numSize/2;d>0;d/=2){//取步长
for(int i=d;i<numSize;i++){//遍历步长
//插入法
int temp=A[i];
int j=i;
while(j-d>=0&&temp<A[j-d]){
A[j]=A[j-d];
j-=d;
}
if(j!=i){
A[j]=temp;
}
}
}
}
3.交换排序–冒泡排序(稳定的排序算法)
//冒泡排序。
//时间复杂度:最好情况下:O(n)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void BubbleSort(int* A,int numSize){
bool flag;//判断是否已经有序
for(int i=0;i<numSize-1;i++){
flag=false;
for(int j=numSize-1;j>i+1;j--){//冒泡
if(A[j]<A[j-1]){//交换
A[j]=A[j]^A[j-1];
A[j-1]=A[j]^A[j-1];
A[j]=A[j]^A[j-1];
flag=true;
}
}
if(!flag){
return;
}
}
}
4.交换排序–快速排序(不稳定的排序算法)
//分治
int Partition(int* A,int low,int high){
int standard=A[low];//基准值
while(low<high){//根据基准值划分数组
while(low<high&&A[high]>=standard) high--;//从左找比基准值小的数
A[low]=A[high];
while(low<high&&A[low]<=standard) low++;//从右找比基准值大的数
A[high]=A[low];
}
A[low]=standard;
return low;
}
//快速排序。
//时间复杂度:最好情况下:O(nlogn)。最坏情况下:O(nlogn);
//空间复杂度:O(logn)
void QuickSort(int *A,int low,int high){
if(low<high){
int partition=Partition(A,low,high);//枢轴
QuickSort(A,low,partition-1);//枢轴左排序
QuickSort(A,partition+1,high);//枢轴右排序
}
}
5.选择排序–简单选择排序(不稳定的排序算法)
//选择排序。
//时间复杂度最好情况下:O(n^2)。最坏情况下:O(n^2);
//空间复杂度:O(1)
void SelectSort(int* A,int numSize){
int min;//记录最小值下标
for(int i=0;i<numSize-1;i++){
min=i;//最小值的下标
for(int j=i+1;j<numSize;j++){
if(A[j]<A[min]){
min=j;
}
}
if(min!=i){//交换
A[min]=A[i]^A[min];
A[i]=A[i]^A[min];
A[min]=A[i]^A[min];
}
}
}
6.选择排序–堆排序(不稳定的排序算法)
void Swap(int* A,int i,int j){
A[i]=A[j]^A[i];
A[j]=A[j]^A[i];
A[i]=A[j]^A[i];
}
//数组大根堆化
void Heapify(int* A,int n,int i){
int c1=2*i+1;//左子结点
int c2=2*i+2;//右子结点
int max=i;//根结点
if(c1<n&&A[max]<A[c1]){//判断根节点与左子结点的大小
max=c1;
}
if(c2<n&&A[max]<A[c2]){//判断根节点与右子结点的大小
max=c2;
}
if(max!=i){
Swap(A,max,i);//交换数组的两个元素
Heapify(A,n,max);//递归向下heapify
}
}
//建堆
void BuildMaxHeap(int* A,int n){
for(int i=(n-1)/2;i>=0;i--){
Heapify(A,n,i);
}
}
//堆排序。
//时间复杂度:最好情况下:O(nlogn)。最坏情况下:O(nlogn);
//空间复杂度:O(1)
void HeapSort(int* A,int n){
BuildMaxHeap(A,n);//建堆
for(int i=n-1;i>0;i--){
Swap(A,0,i);
Heapify(A,i,0);
}
}
7.归并排序(稳定的排序算法)
#include<stdio.h>
#include<stdlib.h>
int *auk;
void Merge(int* A,int low,int mid,int high){
int i=low,j=mid+1,k;
for(k=low;k<=high;k++){//复制数组的值到辅助数组
auk[k]=A[k];
}
for(k=low;k<=high;k++){//左右区间的数比较
if(i>mid){//左区间数用完,则取右区间的数
A[k]=auk[j++];
}else if(j>high){//右区间数用完,则取左区间的数
A[k]=auk[i++];
}else if(auk[i]>auk[j]){//左区间当前数大于右区间当前数,则取右区间的数
A[k]=auk[j++];
}else{//右区间当前数大于左区间当前数,则取左区间的数
A[k]=auk[i++];
}
}
}
//归并排序。
//时间复杂度:最好情况下:O(nlogn)。最坏情况下:O(nlogn)
//空间复杂度:O(n)
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);//合并左右区间
}
}
int main(){
int A[]={1,3,2,7,4,9,6,8,5};
auk=(int *)malloc(sizeof(int)*9);//给辅助数组分配空间
MergeSort(A,0,8);//归并排序
for(int i=0;i<9;i++){
printf("%d ",A[i]);
}
}
8.基数排序(稳定的排序算法)
//基数排序(数组实现):
//注意:基数排序的数组不能有负数
//时间复杂度:最好情况下:O(d(n+r))。最坏情况下:O(d(n+r))
//空间复杂度:O(nr)
void BaseSort(int* A,int numSize){
if(numSize<=1) return;
//取得数组中最大的数
int max=0;
for(int i=0;i<numSize;i++){
if(max<A[i]){
max=A[i];
}
}
//取得最大数的位数
int maxDight=1;
while(max/10>0){
maxDight++;
max/=10;
}
//申请一个桶空间
int buckets[10][numSize];
int base=10;//位
//从高位到低位进行桶排序
for(int i=0;i<maxDight;i++){
//存储各个桶中存储元素的数量
int bktLen[numSize];
for(int i=0;i<numSize;i++){
bktLen[i]=0;
}
//分配
for(int j=0;j<numSize;j++){
//获取当前位数字大小
int whichBucket=(A[j]%base)/(base/10);
//分配进对应数字大小的桶中
buckets[whichBucket][bktLen[whichBucket]]=A[j];
bktLen[whichBucket]++;
}
//收集:从低位到高位将不同桶中的数据挨个取出来,为下一轮高位排序做准备
int k=0;
for(int b=0;b<10;b++){
for(int p=0;p<bktLen[b];p++){
A[k++]=buckets[b][p];
}
}
base*=10;
}
}
若用链表实现:
时间复杂度:最好情况下:O(d(n+r))。最坏情况下:O(d(n+r))
空间复杂度:O(r)