排序算法代码总结

排序算法代码总结

前言

以下排序方法都是从1至n的排序

int main()
{
	int n;
	int a[10010];

	//输入
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	//直接插入排序
	InsertSort(a, n);

	//折半插入排序
	//InsertSort2(a, n);

	//冒泡排序
	//BubbleSort(a, n);

	//快速排序
	// QuickSort(a, 1, n);

	//简单选择排序
	//SelectSort(a, n);

	//堆排序
	//HeapSort(a, n);

	//归并排序
	//MergeSort(a, 1, n);

	//输出
	for(int i=1;i<=n;i++)
	{
		printf("%d ", a[i]);
	}
	
	return 0;
}

直接插入排序

基本思想:对于有 n 个初始元素的序列,将第 2 至 n 个元素依次插入前面已排好序的子序列中,从而使序列整体有序

void InsertSort(int a[], int n)
{
	int i,j;
	for(i=2;i<=n;i++)//将a[2]-a[n]依次插入前面已排序序列
	{
		if(a[i]<a[i-1])//a[i]值比前驱小,将其插入有序表中
		{
			a[0]=a[i];	//a[0]不存储值,只起辅助交换作用
			for(j=i-1;a[0]<a[j];j--)//从后往前查找待插入的位置
				a[j+1]=a[j];
			a[j+1]=a[0];//插入找到的位置
		}
	}
}

折半插入排序

折半插入排序是在直接插入排序算法上的改进,由于是顺序存储的线性表,所以查找有序子表时可以用折半查找来实现。确定待插入位置后,就可统一地向后移动元素

void InsertSort2(int a[], int n)
{
	int i,j,low,mid,high;
	for(i=2;i<=n;i++)//将a[2]-a[n]依次插入前面已排序序列
	{
		a[0]=a[i];		//用a[0]暂存a[i]的值
		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;j--)	//统一后移元素
		{
			a[j+1]=a[j];
		}
		a[high+1]=a[0];		//将值插入对应位置
	}
}

冒泡排序

基本思想:从后往前两两比较相邻元素的值,若为逆序则交换它们,直到序列比较完。

void BubbleSort(int a[], int n)
{
	bool flag;//一趟冒泡是否发生交换的标志
	int tmp;	//用于辅助交换的元素
	for(int i=1;i<n;i++)//n-1趟冒泡
	{
		flag=false;
		for(int j=n;j>i;j--)//一趟冒泡过程
		{
			if(a[j-1]>a[j])//逆序则交换
			{
				tmp=a[j-1];
				a[j-1]=a[j];
				a[j]=tmp;
				flag=true;
			}
		}
		if(flag==false)//一趟冒泡没有交换,则序列已经有序
			return;
	}
}

快速排序

基本思想:选取一个记录(一般选取第一个记录)作为枢纽(哨兵),然后将所有关键字比它小的记录都放在它的位置之前,将所有关键字比它大的记录都放在它的位置之后。由此,以该 “哨兵” 记录最后所落的位置 i 为分界线,将整个序列分割成两个子序列,对子序列继续重复上述操作。

int Partition(int a[], int low, int high)
{
	int tmp = a[low];	//通常将第一个元素当成哨兵
	while(low < high)
	{
		while(low<high && a[high]>=tmp)//比哨兵小的元素移动到左边
			high--;
		a[low] = a[high];
		while(low<high && a[low]<=tmp)//比哨兵大的元素移动到右边
			low++;
		a[high] = a[low];
	}
	a[low] = tmp;	//哨兵放到最终位置
	return low;
}
void QuickSort(int a[], int l, int r)
{
	if(l<r)
	{
		int p = Partition(a, l, r);	//寻找哨兵
		QuickSort(a, l, p-1);		//分割为两个子序列,再分别排序
		QuickSort(a, p+1, r);
	}
}

简单选择排序

基本思想:第 i 趟在后面 n-i+1 个待排序元素中选取关键字最小的元素,作为有序子序列的第 i 个元素,直到 n-1 趟做完,待排序元素只剩下一个,就不用再选了。

void SelectSort(int a[], int n)
{
	int min=0,tmp=0;//记录位置的元素,辅助元素
	for(int i=1;i<n;i++)
	{
		min=i;//记录最小元素的位置
		for(int j=i+1;j<=n;j++)//选出最小元素
		{
			if(a[j]<a[min])
			{
				min=j;		//更新最小元素位置
			}
		}
		if(min!=i)	//找到最小元素则交换
		{
			tmp=a[i];
			a[i]=a[min];
			a[min]-a[i];
		}

	}
}

堆排序

堆是具有下列性质的完全二叉树:每个结点的值都小于或等于其左右孩子结点的值(称为小根堆),或每个结点的值都大于或等于其左右孩子结点的值(称为大根堆)。堆采用一维数组存储

堆排序的基本思想:首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最小者,然后将它从堆中移走,并将剩余的记录再调整成堆,这样又找出了次小的记录,以此类推,直到堆中只有一个记录。

//调整
void HeapAdjust(int a[], int k, int n)
{
	int top = a[k];	//暂存子树的根结点
	for(int i=2*k;i<=n;i*=2)//沿k较大的子结点向下筛选
	{
		if(i<n && a[i]>a[i+1])//取k较小的子结点的下标
			i++;
		if(top<=a[i])	//筛选结束
			break;
		else
		{
			a[k]=a[i];	//将a[i]调整到双亲结点上
			k=i;		//修改k值,继续筛选
		}
	}
	a[k] = top;	//将调整前的堆顶记录插入到k位置
}
//建小根堆
void HeapSort(int a[], int n)
{
	for(int i=n/2; i>0; i--)//初始化小根堆
	{
		HeapAdjust(a, i, n);
	}
	int tmp=0;
	for(int i=n;i>1;i--)//n-1调整
	{
		tmp = a[1];
		a[1] = a[i];
		a[i] = tmp;			//将堆顶记录与未排序的最后一个记录交换
		HeapAdjust(a, 1, i-1);//重新调整为小根堆
	}
}

如果要建立大根堆,只需要把筛选的条件反过来即可

if(i<n && a[i]<a[i+1])//取k较大的子结点的下标
	i++;
if(top>=a[i])	//筛选结束
	break;

归并排序

基本思想:设初始序列含有 n 个记录,则可看成 n 个有序的子序列,每个子序列长度为 1。

两两合并,得到 ⌊ n / 2 ⌋ \lfloor n/2 \rfloor n/2个长度为 2 或 1 的有序子序列。

再两两合并,……如此重复,直至得到一个长度为 n 的有序序列为止。

int b[10010];	//辅助数组B
//归并函数
void Merge(int a[], int low, int mid, int high)
{
	for(int k=low;k<=high;k++)//将A所有元素复制到B
	{
		b[k]=a[k];
	}
	int i,j,k;
	for(i=low,j=mid+1,k=i; i<=mid && j<=high; k++)
	{
		//比较B中左右两段的元素,将较小值复制到A
		if(b[i]<=b[j])
			a[k]=b[i++];
		else
			a[k]=b[j++];
	}
	while(i<=mid)	//若第一段还有元素,复制到A中
		a[k++]=b[i++];
	while(j<=high)	//若第二段还有元素,复制到A中
		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);	//归并
	}
}

归并排序需要一个辅助数组 B,其长度与原数组 A 相同即可。

排序算法比较

排序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值