Shaker排序法(改进冒泡排序法)(数据结构)

问题引入

先看看实现冒泡排序的代码部分:

//借助宏定义实现元素交换,可以修改为函数
#define SWAP(x,y) {int t; t = x; x = y; y = t;} 

//循环体
for(i = 0; i < MAX-1 && flag == 1; i++){ 
	flag = 0;//状态标志
	for(j = 0; j < MAX-i-1; j++){ 
		if(number[j+1] < number[j]){
            //交换元素值 
			SWAP(number[j+1], number[j]); 
			flag  =  1;//状态标志
		}
	}
}

        可以看出,在冒泡排序法的基础上使用了标志状态判断这一方式,以此改进冒泡排序的速度。

问题分析

        在上述情况下的冒泡排序法的交换动作不会一直进行到最后一个才结束,而是进行到 MAX-1-i 就会结束,右边排序好的元素会一直增加,使得左边排序的次数逐渐减少。

        例如:

        排序前:95 27 90 49 80 58 6 9 18 50

第1步:27 90 49 80 58 6 9 18 50 [95] 95浮出

第2步:27 49 80 58 6 9 18 50 [90 95] 90浮出

第3步:27 49 58 6 9 18 50 [80 90 95] 80浮出

第4步:27 49 6 9 18 50 [58 80 90 95] 58浮出

第5步:27 6 9 18 49 [50 58 80 90 95] 50浮出

第6步:6 9 18 27 [49 50 58 80 90 95] 49浮出

第7步:6 9 18 [27 49 50 58 80 90 95]  排序结束

        方括号内的元素表示已排序完成。Shaker排序使用了这个概念,如果让左边的元素也具有这样的性质,让左右两边的元素都能先排序完成,如此未排序的元素会集中在中间,由于左右两边同时排序,中间未排序的部份将会很快的减少。

问题的关键就在于如何实现 双向进行 排序。先从左向右进行,再从右向左进行,完成一次排序的动作,使用left、right两个标志记录左右两端已排序的元素位置。

例如:

        排序前:45 19 77 81 13 28 18 19 77 11

往右排序:19 45 77 13 28 18 19 77 11 [81]

向左排序:[11] 19 45 77 13 28 18 19 77 [81]

往右排序:[11] 19 45 13 28 18 19 [77 77 81]

向左排序:[11 13] 19 45 18 28 19 [77 77 81]

往右排序:[11 13] 19 18 28 19 [45 77 77 81]

向左排序:[11 13 18] 19 19 28 [45 77 77 81]

往右排序:[11 13 18] 19 19 [28 45 77 77 81]

向左排序:[11 13 18 19 19] [28 45 77 77 81]

括号中元素表示左右两边已排序完成,若left > right,则排序结束。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SWAP(x,y) {int t; t = x; x = y; y = t;} //借助宏定义实现元素交换,可以修改为函数
#include<iostream>
using namespace std;
 
void bubsort(int number[]){ 
	int i, j, k, flag = 1;
	for(i = 0; i < MAX-1 && flag == 1; i++){ 
		flag = 0;
		for(j = 0; j < MAX-i-1; j++){ 
			if(number[j+1] < number[j]){
                //此处可以将SWAP宏定义中的交换修改为元素在内部交换
				SWAP(number[j+1], number[j]);
				flag = 1;
			}
		}
		cout<<"第 "<<i+1<<" 次排序:"; 
		for(k = 0; k < MAX; k++){
			cout<<number[k]<<' ';
		}
		cout<<endl;
	}
}
 
int main(){
	int number[MAX] = {0}; 
	int i;
	srand(time(NULL)); //刷新每次产生的随机数,若无此句,每次随机数相同,亲自尝试一下便知
	cout<<"\n冒泡排序:\n\n";
	cout<<"排序前:";
	for(i = 0; i < MAX; i++){ 
		number[i] = rand() % 100; //产生0-99的随机数,这里没有采用固定的数组值进行排序,随机生成
		cout<<number[i]<<' ';
	}
	cout<<endl<<endl;
	bubsort(number);
	return 0;
}
 

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

等日出看彩虹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值