目录
C语言八大排序
1、插入排序
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void print(int a[], int n,int i)
{
cout<<i <<":";
for(int j= 0; j<8; j++)
{
cout<<a[j] <<" ";
}
cout<<endl;
}
void InsertSort(int a[], int n)
{
for(int i= 1; i<n; i++)
{
if(a[i] < a[i-1]) //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
{
int j= i-1;
int x = a[i]; //复制为哨兵,即存储待排序元素
a[i] = a[i-1]; //先后移一个元素
while(x < a[j]) //查找在有序表的插入位置
{
a[j+1] = a[j];//元素后移
j--;
if(j==-1)//这里要跳出,不然j=-1时a[-1]会进行判断
break;
//cout<<j<<endl;
}
//找到小于或等于x
//cout<<a[j+1]<<endl;
a[j+1] = x; //插入到正确位置
}
print(a,n,i); //打印每趟排序的结果
}
}
int main()
{
int a[8] = {3,11,5,7,2,4,9,6};
InsertSort(a,8);
print(a,8,8);
}
2、希尔排序
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void ShellSort(int arr[],int N)
{
int i,j,gap;
for(gap = N/2;gap>0;gap/=2)
{
// 每组进行插入排序
for(i=0;i<N;i++)
{
//直插排序,找到比它小的停止
for(j=i-gap;j>=0;j-=gap)
{
if(arr[i]>arr[j])
break;
}
int temp = arr[i];//及记录这个位置
for(int k=i;k>j;k-=gap)//
arr[k] = arr[k-gap];
arr[j+gap] = temp;
}
// 打印当前的gap和序列状态
cout<<"\ngap="<<gap;
cout<<"\ncurrent list:";
for(int h=0;h<N;h++)
cout<<arr[h]<<" ";
}
}
int main()
{
int a[11] = {12,45,90,1,34,87,-3,822,23,-222,32};
cout<<"原始数列:";
for(int i=0;i<11;i++)
cout<<a[i]<<" ";
cout<<endl;
cout<<"希尔排序:";
ShellSort(a,11);
system("pause");
return 0;
}
3、简单选择排序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int a[] = {2,3,7,3,40,34,6};
int size = sizeof(a)/sizeof(int);
for(int i=0;i<size-1;i++)
{
int mn=i;
for(int j=i+1;j<size;j++)
{
if(a[mn]>a[j])
mn = j;
}
if(mn!=i)
swap(a[mn],a[i]);
}
for(int i=0;i<size;i++)
cout<<a[i]<<" ";
return 0;
}
4、堆排序
#include<bits/stdc++.h>
using namespace std;
void HeapAdjust(int *a,int i,int size) //调整堆
{
int lchild=2*i; //i的左孩子节点序号
int rchild=2*i+1; //i的右孩子节点序号
int max=i; //临时变量,记录父节点
if(i<=size/2) //如果i是叶节点就不用进行调整
{
//如果左子树大于这父节点
if(lchild<=size&&a[lchild]>a[max])
{
max=lchild;
}
//如果右子树大于(左子树和父节点中比较大的值)
if(rchild<=size&&a[rchild]>a[max])
{
max=rchild;
}
//如果右孩子的
if(max!=i)//说明该有孩子节点会比父节点的值大
{
swap(a[i],a[max]);
//继续向下遍历如果它的左孩子和右孩子比它大,再次交换
HeapAdjust(a,max,size); //避免调整之后以max为父节点的子树不是堆
}
}
}
void BuildHeap(int *a,int size) //建立堆
{
int i;
for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2,并且向上遍历非叶子结点
{
HeapAdjust(a,i,size);
}
}
void HeapSort(int *a,int size) //堆排序
{
int i;
BuildHeap(a,size);
for(i=size;i>=1;i--)
{
//cout<<a[1]<<" ";
swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆
}
}
int main(int argc, char *argv[])
{
int a[]={0,16,20,3,11,17,8};
//int a[100];
int size;
size = sizeof(a)/4-1;//szie是6,sizeof进行统计的时候,一个int按4个记
//cout<<size<<endl;
int i;
HeapSort(a,size);
for(i=1;i<=size;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
5、冒泡排序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int a[] = {4,3,2,0,7,9,2};
int size = sizeof(a)/sizeof(int);
for(int i=0;i<size-1;i++)
{
for(int j=0;j<size-i-1;j++)
{
if(a[j]>a[j+1])
swap(a[j],a[j+1]);//交换
}
}
for(int i=0;i<size;i++)
cout<<a[i]<<" ";
return 0;
}
6、快速排序
#include <bits/stdc++.h>
using namespace std;
void quickSort(int left, int right, int arr[])
{
if(left >= right)
return;
int i, j, base, temp;
i = left, j = right;
base = arr[left]; //取最左边的数为基准数
while (i < j)
{
//右边的哨兵开始向左遍历,直到遇见比基准值小的
while (arr[j] >= base && i < j)
j--;
//左边哨兵开始向右边遍历,直到遇见比基准值大的
while (arr[i] <= base && i < j)
i++;
if(i < j)//两个哨兵交换值
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//基准数归位
arr[left] = arr[i];//最左边的数(基准值)等于停止位置的值
arr[i] = base;//停止的位置等于基准值
quickSort(left, i - 1, arr);//递归左边
quickSort(i + 1, right, arr);//递归右边
}
int main()
{
int a[] = {10,3,4,6,9,7,4};
int size = sizeof(a)/4;
quickSort(0,size-1,a);
for(int i=0;i<size;i++)
printf("%d ",a[i]);
return 0;
}
7、归并排序
#include <stdio.h>
void MergeArr(int* src,int * tmp,int start,int mid,int end)
{
int i = start;//前半部分
int j = mid + 1;//后半部分
int k = start;
while (i != mid + 1 && j != end + 1) //进行合并
{
if (src[i] < src[j])
tmp[k++] = src[i++];
else
tmp[k++] = src[j++];
}
if (i == mid + 1)
{
while (j != end+1)
tmp[k++] = src[j++];
}
else
{
while (i != mid + 1)
tmp[k++] = src[i++];
}
while (start <= end)//这是把排好序的数组存回去
{
src[start] = tmp[start];
start++;
}
}
void MergeSort(int* arr, int * tmp,int start,int end) //归
{
if (start < end)
{
int mid = (start + end) / 2;
MergeSort(arr, tmp,start,mid);//开始分割,前半部分
MergeSort(arr, tmp, mid+1, end);//后半部分
MergeArr(arr, tmp, start, mid, end);//进行合并
}
}
int main()
{
int a[8] = { 2,4,5,9,1,6,7,8 };
int c[8] = {0};
MergeSort(a, c, 0, 7);
for (int i = 0; i < 8; i++)
{
printf("%d\t", c[i]);
}
return 0;
}
8、基数排序
#include<bits/stdc++.h>
using namespace std;
#define Max_ 10 //数组个数
#define RADIX_10 10 //整形排序
#define KEYNUM_31 10 //关键字个数,这里为整形位数
// 打印结果
void Show(int arr[], int n)
{
int i;
for ( i=0; i<n; i++ )
printf("%d ", arr[i]);
printf("\n");
}
// 找到num的从低到高的第pos位的数据
int GetNumInPos(int num,int pos)
{
int temp = 1;
for (int i = 0; i < pos - 1; i++)
temp *= 10;
return (num / temp) % 10;
}
//基数排序 pDataArray 无序数组;iDataNum为无序数据个数
void RadixSort(int* pDataArray, int iDataNum)
{
int *radixArrays[RADIX_10]; //分别为0~9的序列空间
for (int i = 0; i < 10; i++)
{
radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));
radixArrays[i][0] = 0; //index为0处记录这组数据的个数
}
for (int pos = 1; pos <= KEYNUM_31; pos++) //从个位开始到10位
{
for (int i = 0; i < iDataNum; i++) //分配过程
{
int num = GetNumInPos(pDataArray[i], pos);//获取该对应位置上的值
int index = ++radixArrays[num][0];//所储存在数组中的位置
radixArrays[num][index] = pDataArray[i];//放进筒里
}
for (int i = 0, j =0; i < RADIX_10; i++) //收集
{
for (int k = 1; k <= radixArrays[i][0]; k++)
pDataArray[j++] = radixArrays[i][k];//把筒里的值倒回给原来的数组
radixArrays[i][0] = 0; //复位
}
}
}
int main()
{ //测试数据
int arr_test[Max_] = { 8, 4, 2, 3, 5, 1, 6, 9, 0, 7 };
//排序前数组序列
Show( arr_test, Max_ );
RadixSort( arr_test, Max_);
//排序后数组序列
Show( arr_test, Max_ );
return 0;
}
时间,空间复杂度,以及稳定性对比总结
如果只想得到1000个元素组成的序列中第5个最小元素之前的部分排序的序列,用()方法最快
-
起泡排序
-
快速排序
-
希尔排序
-
堆排序
-
简单选择排序
一般这种求前元素中前几个最小或者最大的元素,一般都是选择堆排序