冒泡排序,插入排序,选择排序,堆排序代码

冒泡排序

void bubble_sort(int *ar, int size)
{
	assert(ar != NULL);
	for (int i = 0; i < size - 1; i++)
	{
		for (int j = 0; j < size - i - 1; j++)
		{
			if (ar[j]>ar[j + 1])
			{
				swap(ar[j], ar[j + 1]);
			}
		}
	}

}

容易出现错误的地方是for (int j = i; j < size - i - 1; j++),在这里看似没错,但是如果j是由i赋值的话每次比较大小的开始就不是第一个了,而实跟着i开始比较,这样就会少比较几个数

void bubble_sort2(int *ar, int size)
{
	assert(ar != NULL);
	if (size < 2)
	{
		return;
	}
	//int flag1 = 0;
	//int flag2 = 0;
	for (int i = 0; i < size - 1; i++)
	{
		bool tag = true;
		for (int j = 0; j < size - i - 1; j++)
		{
			if (ar[j]>ar[j + 1])
			{
				swap(ar[j], ar[j + 1]);
		/*		flag2++;*/
				tag = false;
			}					
		}
		/*if (flag1 != flag2)
		{
			flag1 = flag2;
		}
		else break;*/
		if (tag)
		{
			break;
		}
	}

}

第二个版本的冒泡排序加了一个标识位,如果只需要移动第一位,而其他位不用动,那么加了标识位后,通过break可以跳出剩余无用循环

选择排序

void SelectSort(SeqList &seq)   选择排序
{
	int n = GetSize(seq);
	for(int i = 0;i<n-1;++i)
	{
		int minpos = i;
		for(int j = i+1;j<n;++j)
		{
			if(seq.data[minpos] > seq.data[j])
			{
				minpos = j;
			}
		}
		if(i != minpos)
		{
			Swap(seq.data[minpos],seq.data[i]);
		}
	}
}

插入排序

void InsertSort(SeqList &seq)
{
	int n = GetSize(seq);
	for(int i = 1;i<n;++i)
	{
		if(seq.data[i] < seq.data[i-1])
		{
			ElemType tmp = seq.data[i];
			int j = i - 1;
			do
			{
				seq.data[j+1] = seq.data[j];
				--j;
			}while(j >= 0 && tmp < seq.data[j]);
			seq.data[j+1] = tmp;
		}
	}
}



void FilterDown(SeqList &seq,int start,int end)//建立最小堆,为优先级队列和排序做先觉条件
{
	int i = start,j = 2*i+1;
	ElemType tmp = seq.data[i];//用于最后完成建立后交换原来根节点的值
	while(j <= end) //
	{
		if(j < end && seq.data[j] < seq.data[j+1]) ++j; // Max
		if(tmp >= seq.data[j]) break;
		seq.data[i] = seq.data[j];
		i = j;
		j = i*2+1;
	}
	seq.data[i] = tmp;
}

数据结构的本质是数据之间的关系,如一对一,一对多,多对一,多对多

堆排序
的规律是如某节点的下标是i
则其左孩子的下标是2i+1
其右孩子的下标是2
i+2
其双亲的下标是(j-1)/2

如某个数组是:56 78 12 23 90 86 45 34
在这里插入图片描述
现在需要排序
排序的形式为key i
key i<=key i2+1;
key i<=key i
2+2;
在建立最小堆时,我们需要从叶节点往根节点构造,因为如果不降叶节点的最小堆确定,那么在建立根节点的最小堆时无法确定,原理和关键路径的画法很相似
所以上面的堆排序的顺序是
FilterDown(ar,3,7);
FilterDown(ar,2,7);
FilterDown(ar,1,7);
FilterDown(ar,0,7);
在调用函数是需要确定下标的值,这里计算的方式是(i-1)/2
在这里的调用顺序是无法改变的,因为在建立最小堆时,必须先确定其叶节点的最小堆是确定的,否则叶节点以上的节点最小堆也无法确定

如果该数据在末尾增加了一个数
如某个数组是:56 78 12 23 90 86 45 34 5
那么原来的最小堆就不是最小堆了我们需要重新建立
这时候如果将整个二叉树进行排序那么十分浪费时间
我们可以选择将加入的数和其双亲节点比较,如果其小于双亲节点,则交换和继续和其双亲节点比较,相当于只对整体的一般的节点进行了排序,这样的效率较高

void FilterDown(elemtype*ar, int start)//在8下标插入,所以start=8,这时的ar是已近插入了第8个数
{
	int i = start;
	int j = (i - 1) / 2;
	while (i != 0)
	{
		if (ar[i] < ar[j])
		{
			swap(ar[i], ar[j]);
			i = j;
			j = (i - 1) / 2;
		}
		break;
	}
}

堆排序完后取值时,先取根节点(0下标的值),然后把末尾下标的值放在0下标的位置,然后从根节点重新建立最小堆,之后在此取根节点的值,这就是堆排序的核心
下面附上堆排序在优先级队列中的应用

void FilterDown(ElemType *ar,int start,int end)
{
	int i = start,j = 2*i+1; // 
	ElemType tmp = ar[i];
	while(j <= end)
	{
		if(j < end && ar[j] > ar[j+1]) j+=1;
		if(tmp <= ar[j]) break;
		ar[i] = ar[j];
		i = j;
		j = 2*i+1;
	}
	ar[i] = tmp;
}

void FilterUp(ElemType *ar,int start)
{
	int j = start, i = (j-1)/2;
	ElemType tmp = ar[j];
	while(j > 0)
	{
		if(ar[i] <= tmp) break;
		ar[j] = ar[i];
		j = i;
		i = (j-1)/2;
	}
	ar[j] = tmp;
}

下面举例优先级队列的输入和输出的例子

void FilterDown(ElemType *ar,int start,int end)
{
	int i = start,j = 2*i+1; // 
	ElemType tmp = ar[i];
	while(j <= end)
	{
		if(j < end && ar[j] > ar[j+1]) j+=1;
		if(tmp <= ar[j]) break;
		ar[i] = ar[j];
		i = j;
		j = 2*i+1;
	}
	ar[i] = tmp;
}

void FilterUp(ElemType *ar,int start)
{
	int j = start, i = (j-1)/2;
	ElemType tmp = ar[j];
	while(j > 0)
	{
		if(ar[i] <= tmp) break;
		ar[j] = ar[i];
		j = i;
		i = (j-1)/2;
	}
	ar[j] = tmp;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值