数据结构-排序

1 知识框架

在这里插入图片描述

算法的稳定性:;两个相同的元素在排序算法完成后,两者的相对位置还没改变,则算法是稳定的。
内部排序算法总览:
在这里插入图片描述

2 插入排序

2.1 直接插入排序

//      升序排列L[]
void insertSort(int L[],int n)
{
	for(int i = 2;i <= n;i ++)
	{
		if(L[i] < L[i - 1])
		{
			L[0] = L[i-1];
			for(int j = i - 1;L[0] < L[j];j --)
			{
				L[j + 1] = L[j];
			}
			L[j + 1] = L[0];
		}
	}
}    // L[0] 哨兵作用

空间效率:仅使用常数个辅助单元,因此为O(1)。
时间效率:最好的情况O(n),最坏的情况O(n²),因此时间复杂度为O(n²)

2.2 折半插入排序

直接插入是边比较边插入,折半先找到元素要插入的位置,然后统一移动元素

void insertSort(int L[],int n)
{
	int i,j,low,high;
	for(i = 2;i <= n;i ++)
	{
		L[0] = L[i];
		low = 1,high = i - 1;
		while(low <= high)
		{
			mid = (low + high) / 2;
			if(L[mid] > L[0]) high = mid -1;
			else low = mid + 1;
		}  // 找出待插入位置
		for(j = i - 1;j >= high + 1;j --)
		{
			L[j + 1] = L[j];
		}//  统一移动元素
		L[high + 1] = L[0];
	}
}

改变了元素的比较次数,移动次数并没有改变,时间复杂度仍为O(n²)。
但他适用于数据量不大的排序表。

2.3 希尔排序

void insertSort(int L[],int n)
{
	int i,j,dk;
	for(dk = n / 2;dk >= 1;dk = dk / 2)   //dk的选取以及变化不是固定的
		for(i = dk + 1;i <= n; i ++)
			if(L[i] < L[i - dk])
				{
					L[0] = L[i];
					for(j = j - dk;j > 0 && L[0] < L[j]; j-= dk)
						{
							L[j + dk] = L[j]     //元素后移
						}
					L[j + dk] = L[0];
				}
}

空间:O(1)
时间:涉及dk的选取,时间分析比较困难,约为O(n的1.3次方)
适用线性表为顺序存储的情况

3 交换排序

3.1 冒泡排序

void bubbleSort(int l[],int n)
{
	int temp;
	for(int i = 0;i <= n;i ++)                //比较次数
		for(int j = n - 1;j > i;j --)
			{
				if(l[j] < l[j - 1)
				{
					temp = l[j];
					l[j] = l[j - 1];
					l[j - 1] = temp;
				}
			}
}

空间:使用常数辅助,为O(1)
时间:平均时间复杂度O(n²)

3.2 快排

#include<stdio.h>
int n,i,j,a[100];  //定义全局变量 

void quicksort(int left, int right)   
{
	int temp,t;   //temp变量是基准,t变量是用来交换的第三变量 
	if(left > right)   //跳出循环的第一个条件 
	{
		return;
	}
	
	temp = a[left];   //此时选用的是第一个数当做基准 
	i = left;     //i是1 
	j = right;     //j是n 
	while(i != j)     //当i,j没有走到一块的时候 
	{
		while(a[j] >= temp && i<j)   //j一步一步左移,查找比基准值小的数 
		{
			j--;
		}
		while(a[i] <= temp && i<j)   //i一步一步右移,查找比基准值大的数 
		{
			i++;
		}
		if(i < j)
		{
			t = a[i];    //将j查到的比基准值的数与i查到的比基准值小的数交换 
			a[i] = a[j];  //即将小的数放在基准值左边 
			a[j] = t;      //将大的数放在基准值右边 
		}
	}
	  //将基准值归位 
	a[left] = a[i];    //当循环结束时,i=j,在中间某一位置 
	a[i] = temp;      //将那一位置的数与基准值交换 
	
	//递归 ,将基准值左边分为一部分
   //将基准值右边分为一部分 
	quicksort(left,i-1);     //继续处理左半部分的数    
	quicksort(i+1,right);   //继续处理右半部分的数 
	return ;
}

int main()  //主函数 
{
	scanf("%d",&n);  //用来限制输入的个数 
	for(i=1; i<=n; i++)
	{
		scanf("%d",&a[i]); //读入数据 
	}
	quicksort(1,n);  //调用快排函数 
	for(i=1; i<=n; i++) 
	{
		printf("%d\t",a[i]);  //循环输出 
	}
}


通过二叉树来判断 每次选取左边第一个数做根结点
在这里插入图片描述
空间:平均情况栈的深度为O(log₂n)
时间:平均复杂度为O(nlog₂n)
快排是所有内部排序算法中平均性能最优的排序算法

4 选择排序

4.1 简单选择排序

void selectSort(int l[],int n)
{
	for(int i = 0;i < n - 1;i ++)
	{
		int min = i;
		for(int j = i + 1;j < n;j ++)
			if(l[j] < l[min])min = j;
		if(min != i)swap(l[i],l[min]);
	}
}

空间:O(1)
时间:O(n²)

4.2 堆排序

1.构造初始堆
架设构造大根堆
第一步从n / 2 - 1 ~ 1的顺序,看该结点的值是否小于子结点的值,若小于,则与子结点较大值交换。
第二步,若交换后的结点破坏了下一级的堆,子结点采用第一步的方法构造下一级堆。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.输出堆顶元素
3.将堆底元素送入堆顶,重新构造堆
重新构造的堆的方法就是第二步

空间:O(1)
时间:平均复杂度为O(nlog₂n)

5 归并和基数排序

5.1 归并排序

将n个有序的子表,两两合并,直到合并成一个长度为n的有序表,称为2路归并排序
在这里插入图片描述
如何将两个子表合并:
假设两端有序表为A[l,m],A[m + 1,h]将两个表复制到B数组中,分别从两端取数进行比较,将较小的存入A中,一段会先存完,将没有存完的剩下那段的数字直接复制到A中

void merge(int a[],int l,int m,int h)
{
	for(int i = l;i <= h;i ++)
		b[i] = a[i];
	for(i = l,j = mid + 1,k = i;i <= mid&& j <= h;k ++)
	{
		if(b[i] <= b[j])            // 较小放入a中
			a[k] = b[i ++];
		else
			a[k] = b[j ++];
	}
	while(i <= mid) a[k ++] = b[i ++];  // 第一个表没复制完
	while(j <= h) a[k ++] = b[j ++];	// 第二个表没复制完
}

空间复杂度:O(n)
时间:平均复杂度为O(nlog₂n)

5.2 基数排序

通常有两种方法:
1,最高位优先(MSD)
2,最低位优先(LSD)
举例低位优先
在这里插入图片描述

在这里插入图片描述
最后是得出的有序序列
空间:使用r个队列,因此为O®
时间:进行d趟收集和分配,一趟分配需要O(n),一趟收集需要O®,因此时间复杂度为O(r + n)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值