数据结构中的排序

数据结构中的排序

一、排序的基本术语

1.内部排序:

数据量不大,数据在内存,无需内外存交换数据。

2.外部排序

数据量较大,文件需要外存(如硬盘上的文件排序),外排序远比内排序复杂。

3.排序的稳定性

举个例子:如49,97,76,13,27,49’
稳定排序之后:13,27,49,49’,76,97
不稳定排序之后:13,27,49’,49,76,97

稳定排序在只对结构体(有多种因素影响排序结果)有意义。

二、顺序表

1.顺序表的存储结构
typedef int KeyType;	//定义关键字类型为int
typedef char InfoType;  //数据项为字符型

typedef struct
{
	KeyType key;		//关键字项
	InfoType data;		//其他数据项,类型为InfoType
} RecType;				//查找元素的类型
2.操作顺序表的方法
//交换表中的数据项x和y
void swap(RecType x, RecType y)	
{
	RecType tmp = x;            //采取定义第三方变量的方法
	x = y; y = tmp;
}
//创建顺序表
void CreateList(RecType R[], KeyType keys[], int n)	
{
	for (int i = 0; i < n; i++)	    //将字符数组对应赋值对应数据项,R[]为空,利用关键字进行排序运算
		R[i].key = keys[i];         //将除留余数法得到数组对应赋值关键字数组
}
//输出顺序表
void DispList(RecType R[], int n)	
{
	for (int i = 0; i < n; i++)
		printf("%d ", R[i].key);
	printf("\n");
}

三、快速排序

1.原理

如图所示,每一次以第一个元素为基准

其实快速排序就是三叉树形式,每次都对数组进行截三段,直到每个元素都成叶子。

2.算法

划分算法,一次划分数组为三块

//一趟划分
int partition(RecType R[], int s, int t)	
{
	int i = s, j = t;
	RecType tmp = R[i];			//以R[i]为基准,一般s为0
	while (i < j)  				//从两端交替向中间扫描,直至i=j为止
	{
		while (j > i && R[j].key >= tmp.key)
			j--;				//从右向左扫描,找一个小于tmp.key的R[j]
		R[i] = R[j];				//找到这样的R[j],放入R[i]处
		while (i < j && R[i].key <= tmp.key)
			i++;				//从左向右扫描,找一个大于tmp.key的R[i]
		R[j] = R[i];				//找到这样的R[i],放入R[j]处
	}
	R[i] = tmp;
	return i;
}

主算法

void QuickSort(RecType R[], int s, int t) //对R[s..t]的元素进行快速排序
{
	int i;
	RecType tmp;
	if (s < t) 					//区间内至少存在两个元素的情况
	{
		i = partition(R, s, t);
		QuickSort(R, s, i - 1);		//对左区间递归排序
		QuickSort(R, i + 1, t);		//对右区间递归排序
	}
}
3.算法性能分析

数据移动次数太多,数据量较少时比较合适

四、堆排序
1.原理

(1)其实堆排序最终将无序数组调整成一个有序完全二叉树,根据从大小顺序分为小根堆、大根堆,这里主要讨论小根堆。主要有筛选与调整两个过程
(2)筛选:每次从数组元素中取最小元素作为根,一般左比右小,上肯定比下小,多次递归,建成完全二叉树。

(3)调整:输出根后以最后一个元素代替它。

2.算法

筛选过程

void sift(RecType R[], int low, int high)
{
	int i = low, j = 2 * i;     					//R[j]是R[i]的左孩子
	RecType temp = R[i];
	while (j <= high)
	{
		if (j < high && R[j].key < R[j + 1].key) 	//若右孩子较大,把j指向右孩子
			j++;    						//变为2i+1
		if (temp.key < R[j].key)
		{
			R[i] = R[j];              		//将R[j]调整到双亲结点位置上
			i = j;                    		//修改i和j值,以便继续向下筛选
			j = 2 * i;
		}
		else break;                 		//筛选结束
	}
	R[i] = temp;                      		//被筛选结点的值放入最终位置
}

调整过程

void HeapSort(RecType R[], int n)
{
	int i;
	RecType tmp;
	for (i = n / 2; i >= 1; i--)	//循环建立初始堆,调用sift算法 n/2 次
		sift(R, i, n);
	for (i = n; i >= 2; i--)		//进行n-1趟完成推排序,每一趟堆排序的元素个数减1
	{
		tmp = R[1];			//将最后一个元素与根R[1]交换
		R[1] = R[i];
		R[i] = tmp;
		sift(R, 1, i - 1);		//对R[1..i-1]进行筛选,得到i-1个节点的堆
	}
}
3.算法性能分析

堆排序时间稳定,但是不稳定排序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有几何

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值