算法 - 鸡尾酒排序(CocktailShaker_sort)

目录

引言:

什么是鸡尾酒排序(CocktailShaker_sort)?

鸡尾酒排序的排序原理:

鸡尾酒排序的过程演示:

Step 1 :

Step 2 :

Step 3 :

Step 4 :

Step 5 :

 Step 6 :

 Step 7 :

 Step 8 :

step 9(跳出循环) :  

程序代码(C):

程序验证: 

对鸡尾酒排序的思考和优化:

对鸡尾酒排序的总结:


引言:

鸡尾酒排序是我在算法可视化视频里接触到的一个算法,我发现鸡尾酒排序的算法在排序效率上是优于冒泡排序的,在写鸡尾酒算法的代码之前,我们先对鸡尾酒排序的排序过程和排序原理做一下简单梳理。

什么是鸡尾酒排序(CocktailShaker_sort)?

鸡尾酒排序就是双向冒泡排序,也叫搅拌排序、涟漪排序。我们知道冒泡排序本质上是利用下标对序列中不符合前小后大的两个元素进行交换并循环此过程直到将序列中所有的元素排序完成,在整个排序的过程中,冒泡排序的每一次过程都是从下标为0的第一个元素开始进行排序操作,那么如果我们像折半查找那样定义左边界和右边界,每次排序都在左边界和右边界中轮流进行,结束每次的排序过程后左边界和右边界均缩进一位,直到整个序列排序完成,这样是不是就比单向的冒泡排序的效率提高了很多。

鸡尾酒排序的排序原理:

本质上就是双向或对向的冒泡排序,第一趟是从左边界开始遍历,第二趟开始从右边界开始遍历,每趟完成后边界进行缩进,每趟轮流着进行,直到排序完成。

鸡尾酒排序的过程演示:

例如在这里我给出10个数,分别是:9,15,10,23,6,22,11,12,28,我们就用这9个数来演示鸡尾酒排序的过程:

Step 1 :

定义左边界left和右边界right和下标 i 和 j ,使这两个下标分别对right边界和left边界: 

Step 2 :

此时i下标对序列进行从左向右的第一次遍历,我们使用冒泡排序的规则对序列进行第一次排序,我们将15和10的位置进行调换,将23和6进行交换,交换后我们发现23 大于 22、11、12,调换位置,第二趟位置调换完成之后,i下标对应的right边界向左缩进一位,如下:

Step 3 :

此时i下标回归left边界,j下标开始从右向左的第一次遍历,我们将11、22的位置进行调换,6也小于15、10、9,所以将6进行位置调换,第三趟调换完成之后,将j对应的left边界向右缩进一位,如图:

Step 4 :

此时,j下标回归right边界,i下标开始从左向右的第二次遍历,此时将10、15、11、22、12进行位置调换,调换完成之后i下标对应的right边界向左缩进一位:

​​​​​​​

Step 5 :

此时i下标回归left边界,j下标开始从右向左的第二次遍历,我们将12、15元素进行调换,调换完成后,j下标对应的left边界向右缩进一位,如图:

 Step 6 :

此时j下标回归right边界,i下标开始从左向右的第三次遍历,我们发现10、11、12、15都是符合升序规则的,此时i下标对应的right边界向左缩进一位,如图:

 Step 7 :

此时i下标回归left边界,j下标开始从右向左的第三次遍历,我们发现15、12、11均符合升序规则,则此时j下标对应的left边界向右缩进一位,如图:

 

 Step 8 :

此时j下标回归right边界,i下标开始从左向右的第四次遍历,我们发现12、15均符合升序规则,则此时i下标对应的right边界向左缩进一位,如图:

step 9(跳出循环) :  

此时i下标回归left边界,j下标开始从右向左的第五次遍历,我们发现只剩下一个元素12,此时本应该j下标对应的left边界向右缩进一位,但是这时如果进行缩进操作,就不满足left边界小于right边界的设定,此时我们跳出循环,现在的序列顺序就是排列好的升序顺序:

程序代码(C):

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define MAXSIZE 10
void initar(int *ar,int len)//初始化数组
{assert(ar != nullptr);for(int i = 0;i < len;i++){ar[i] = rand() % 30;}
}
void showar(int *ar,int len)//打印数组
{assert(ar != nullptr);for(int i = 0;i < len;i++){printf("%d ",ar[i]);}printf("\n--------------------------\n");
}
void swap(int *ar,int index1,int index2)//交换函数
{int temp = ar[index1];ar[index1] = ar[index2];ar[index2] = temp;
}
void Cocktail_sort(int *ar,int len)//鸡尾酒排序
{assert(ar != nullptr);int left = 0;//定义左边界int right = len - 1;//由于使用的是下标,所以右边界为长度减一while(left < right){//大循环条件为左边界与右边界不重合for(int i = left;i < right;i++){//从左边界开始从左向右遍历if(ar[i] > ar[i + 1]){swap(ar,i,i + 1);}}right--;每从左至右遍历完一次右边界缩减一个单位for(int j = right;j > left;j--){//从右边界开始从右向左进行遍历if(ar[j - 1] > ar[j]){swap(ar,j - 1,j);}}left++;每从右向左遍历完一次左边界前移一个单位}
}
int main()
{srand((unsigned int)time(NULL));int ar[MAXSIZE];initar(ar,MAXSIZE);printf("原始数据为:\n");showar(ar,MAXSIZE);printf("\n经过鸡尾酒排序后的数据为:\n");Cocktail_sort(ar,MAXSIZE);showar(ar,MAXSIZE);return 0;
}

程序验证: 

我们在每次边界缩进的语句后方都添加一个打印函数语句用来验证我们上面的分析步骤,如图:

可以看到经过9趟排序之后函数最终完成了对数据的排序,和我们上面的分析一致。 

对鸡尾酒排序的思考和优化:

我们对上面的排序过程进行分析,其实在Step 5时,序列就已经基本有序,Step6是对序列顺序的检查,后面的步骤也只是边界的缩进,也就是对循环条件while(left < right)的满足过程,其实Step7、8、9步骤是可以进行优化的,这一点和冒泡排序的优化十分类似因为鸡尾酒排序本身就是属冒泡类的排序方法。

在之前的文章:算法 - 冒泡排序(Bubble_ Sort)https://blog.csdn.net/weixin_45571585/article/details/125174674?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166383825016800182755296%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=166383825016800182755296&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-125174674-null-null.nonecase&utm_term=%E5%86%92%E6%B3%A1&spm=1018.2226.3001.4450中曾经提到冒泡排序的优化:

void Bubble_sort(int *ar,int len)
{int flag = 1;while(len-- && flag){flag = 0;for(int i = 0;i < len;i++){if(ar[i] > ar[i + 1]){flag = 1;swap(ar,i,i + 1);}}}
}

这里就是使用flag标签有效地去减少所要遍历的趟数,同样,我们也可以将次方法运用至鸡尾酒排序中:

#include<iostream>
using namespace std;
void Show(const int *a, int n)
{if(n<=0) return;cout << a[0];for(int i=1; i<n; i++)cout << ", " << a[i];cout << endl;
}void Show(const int *a, int n, int j)	
{int i;if(n<=0) return;if(j==0)cout << "[" << a[0];elsecout << " " << a[0];for(i=1; i<n; i++){if(i==j)cout << ",[" << a[i];else if(i==j+1)cout << ", " << a[i] << "]";elsecout << ", " << a[i];}cout << endl;
}
void CocktailSort(int *a, int n)
{for(int i=0; i<n; i++){int flag = 1;if(i % 2 == 0){cout << "\n第" << i+1 << "轮(从左到右)" << endl;for(int j=i/2; j<1; j++)//后面对取i/2有说明{if(a[j] > a[j+1]){swap(a[j], a[j+1]);flag = 0;}Show(a, n, j);}}else{cout << "\n第" << i+1 << "轮(从右到左)" << endl;for(int j=n-1-i/2; j>i/2; j--){if(a[j-1] > a[j]){swap(a[j-1], a[j]);flag = 0;}Show(a, n, j-1);}}cout << "本轮" << (flag? "无" : "有") << "交换" << endl;if(flag)break;}
}
int main()
{int a[] = {8, 1, 0, 9, 7, 5};//嘿嘿嘿,整个活int n = sizeof(a)/sizeof(*a);cout << "原始数据: ";Show(a, n);CocktailSort(a, n);cout << "\n鸡尾酒排序结果: ";Show(a, n);return 0;
}

运行结果:

  

对鸡尾酒排序的总结:

 鸡尾酒排序实际上是属冒泡排序类的,是冒泡排序的变体形式,它与冒泡排序之间的不同点就在就在于冒泡排序是单向的,而鸡尾酒是双向的。鸡尾酒排序的时间复杂度和冒泡排序一样,它们都是嵌套的双层循环,所以时间复杂度为O(n^2),空间复杂度为O(1)。

鸡尾酒排序相较于冒泡排序可显著的减少排序所进行的趟数,但是相应的,代码量却增加了近一倍。​​​​​​​

参考资料:

c++鸡尾酒排序(优化)_zedkyx的博客-CSDN博客鸡尾酒排序(优化)文章目录鸡尾酒排序(优化)前言一、鸡尾酒排序是什么?二、程序实现步骤1.引入库2.子函数1(输出函数)子函数2(鸡尾酒排序)主函数输出结果![截自leetcode playground](https://img-blog.csdnimg.cn/963f46361c254bf4a731d75874493e19.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAemhttps://blog.csdn.net/zedkyx/article/details/120707502​​​​​​​​​​​​​​【算法分析】排序算法:鸡尾酒排序_hujingshuang的博客-CSDN博客_搅拌排序鸡尾酒排序算法是一种定向的冒泡法排序算法,又叫鸡尾酒搅拌排序、来回排序、涟漪排序等。https://hujingshuang.blog.csdn.net/article/details/48741207?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-3-48741207-blog-102733197.t5_refersearch_landing&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-3-48741207-blog-102733197.t5_refersearch_landing&utm_relevant_index=4

排序算法之鸡尾酒排序原文: 微信公众号:程序员小灰——什么是鸡尾酒排序 1 鸡尾酒排序 鸡尾酒排序是冒泡排序的一种变形。它与冒泡排序的不同之处在于排序时是以双向在序列中进行排序。 2 原理 鸡尾酒排序的原理跟冒泡排序差不多,只不过冒泡排序每一轮的比较都是从左至右依次比较,而鸡尾酒排序则是一轮从左至右比较,下一轮从右至左比较。 假如有一个这样的数组:{2, 3, 4, 5, 6, 7, 8, 1},如果按照冒泡排序的比较方式,会是这样的流程: https://img blog.csdnimg.cn/2018103108512369.png?x oss process=image/watermark,type ZmFuZ3poZW5naGVpdGk,shadow 10,text aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pnY3FmbHFpbmhhbw==,size 16,color FFFFFF,t 70 可以看到其实每次移动的只是元素 1,如果按照冒泡排序的原理,一共需要进行 7 轮比较,显然这是可以进行优化的https://copyfuture.com/blogs-details/202206290916293135 鸡尾酒排序_百度百科鸡尾酒排序又称双向冒泡排序、鸡尾酒搅拌排序、搅拌排序、涟漪排序、来回排序或快乐小时排序, 是冒泡排序的一种变形。该算法与冒泡排序的不同处在于排序时是以双向在序列中进行排序。https://baike.baidu.com/item/鸡尾酒排序/7515196?fr=aladdin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/47628.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

喜力啤酒全球重磅推出全新包装

近日&#xff0c;喜力啤酒于全球范围内重磅推出了全新包装 -- 以高端与时尚为升级基调&#xff0c;通过打造独具匠心的外观设计、别出心裁的磨砂质感以及保留经典独特的标志性口感&#xff0c;突显了喜力的品牌特色&#xff0c;为消费者带来视觉与味觉的双重高端品牌体验&#…

【塔望咨询】X【麦仕醇】开启精酿啤酒新纪元

2021年12月23日&#xff0c;上海麦仕醇啤酒有限公司&#xff08;以下简称“麦仕醇”&#xff09;与塔望Tastewend达成了品牌战略咨询合作关系&#xff0c;双方签署了3W消费战略项目合作协议。 品牌战略合作启动会于麦仕醇公司上海总部举行&#xff0c;麦仕醇公司董事长杨总、总…

Matplotlib及Plotnine绘图正常显示中文的处理方案

最近在python使用matplotlib以及plotnine绘图时&#xff0c;发现绘制的图表无法正常显示中文。花了好一阵子才找到解决方案。记录在此供参考。 一、Matplotlib显示中文的处理方案 首先导入matplotlib模块&#xff0c;绘制一个包含中文的图像&#xff0c;看看是否能正常显示“…

python画图不显示中文的解决方式

解决方式一&#xff1a;修改源文件 1.打开python的安装路径&#xff0c;找到“D:\python\python3.7\Lib\site-packages\matplotlib\mpl-data”路径下的matplotlibrc文件&#xff0c;如下图所示 2.打开matplotlibrc文件之后&#xff0c;将#font.sans-serif : DejaVu Sans, Bit…

使用pycharm画图不显示

问题描述&#xff1a; 使用pycharm画图时&#xff0c;图片不显示并报出如下图错误 解决方案&#xff1a; Settings–Tools–Python Scientific–取消勾选Show plots in tools windows 解决&#xff01;

matplotlib画图不清晰/画图不显示/中文无法显示/图例显示不全/次坐标轴/图例合并

在jupyter_notebook中画图不清晰 加入如下代码运行一次即可&#xff1a; %config InlineBackend.figure_format ‘svg’ 在jupyter_notebook中画图不显示 不加plt.show() ,运行下面的也可以 %matplotlib inline 中文无法显示问题 方法一&#xff1a; import matplotlib.…

终于解决python画图不显示中文的问题了

运行环境mac 发现使用matplotlib等相关绘图包时中文会出现方块&#xff0c;无法显示&#xff0c;试了网上各种方法都不行。。后来发现其实是本地库根本就没有中文字体包&#xff0c;这样的话怎么修改代码都是没用的。。。卒 首先查看是否有相关中文字体包 from matplotlib.f…

解决networkx画图时中文不显示问题

同样遇见了这个问题 插入代码&#xff1a; import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] SimHei解决&#xff1a;

python画图为什么运行不出来_解决python中使用plot画图,图不显示的问题,详细讲解

import matplotlib.pyplot as plt #matplotlib是画图库 as 是起名字 import pandas as pd #padas处理数据dfpd.read_excel(1.xlsx) #打开名字为1.xlsx表 df.plot() #画图工具 有些同学在根据文件画图时&#xff0c;就是以上代…

R中画图不显示图片

R中画图不显示图片 解决方法&#xff1a;一直输入dev.off()&#xff0c;然后再输入dev.new() 重新画图即可。 参考rstudio plot不显示图片了 - 知乎 (zhihu.com)

MPAndroidChart的PieChart不显示扇形,只显示中间文字

想了三四天都不知道咋回事&#xff0c;最后发现是一个很智障的错误。。。   如下所示&#xff1a;   可以看到&#xff0c;有的科目的扇形图是正常显示的&#xff0c;有的没有正常显示。   输出数据&#xff1a; //根据数据对pieChart进行初始化 ArrayList<Integer&…

解决python画图中文不显示问题

python画图&#xff0c;如果用英文显示基本没有问题&#xff0c;但是中文可能会有乱码或者不显示的情况。 经过个人的测试&#xff0c;下图中“横轴”&#xff0c;“纵轴”字样的中文显示没有什么大问题&#xff0c;主要是plt.title部分和plt.plot部分的显示 中文显示问题解…

try catch里面try catch嵌套

try catch里能否内嵌try catch&#xff1f;答案是肯定的。但是等内层try catch出异常之后是个什么执行顺序呢&#xff1f;看下面代码 static void Main(string[] args){try{Console.WriteLine("----------------------外层try------------------------------");error…

余华:把悲伤留给读者,把快乐留给自己

大家好我是图恩&#xff0c;最近看完了余华的一片随笔文集有感&#xff0c;故写下一些记录。 作为把悲伤留给读者把快乐留给自己的代表人物余华给大家贡献了很多笑点&#xff0c;比如听到他讲把史铁生扛上火车带着到处旅游&#xff0c;还讲到带着史铁生跟大学生来了一场足球对…

JSON.stringify()及其使用场景

JSON.stringify()及常用使用场景 JSON.stringify()是一个序列化对象的方法可接收三个参数。第一个参数是要序列化的对象&#xff0c;第二个参数是过滤器&#xff0c;可以是数组或函数&#xff1b;第三个参数是用于缩进结果JSON字符串的选项。 一、过滤器参数 如果第二个参数…

java反射使用总结

一、反射概述 JAVA反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。…

Jeesite 4.0 学习笔记

Jeesite简介 Jeesite是一个 Java EE 企业级快速开发平台。 框架&#xff1a;SpringBoot SpringMVC Apache Shiro MyBatis Beetl&#xff08;模板&#xff09; Boostrap AdminLTE&#xff08;UI&#xff09; 核心模块&#xff1a;组织机构、角色用户、菜单及按钮授权、数…

[英美文化][UMOOCs][英美概况]unit1-7答案分享

自做答案分享 --若有侵权&#xff0c;请联系我删除--

商业研究(14):出境游和自由行,接机-送机-包车-当地玩乐

2015年10月&#xff0c;在36Kr股权众筹平台&#xff0c;参与投资了一个旅游类的项目。 这个项目&#xff0c;主要是做海外出境游&#xff0c;中文接机、中文送机、中文包车&#xff0c;未来可能会有当地玩乐等旅游类项目。 现在过去大概7个月了&#xff0c;进一步熟悉了这个旅游…