第二弹(C++)!!!
以下排序均考虑正负数。。。代码写得好难看

接着上次说~
这次我主要写思想和放代码。。。
- 希尔排序
- 鸡尾酒/双向冒泡排序
- 堆排序
- 桶排序
- 基数排序

Talk is cheap, show you the code!!!

希尔排序

对于直接插入排序问题,数据量巨大时。采用希尔排序。。。
1. 将数的个数设为n,取奇数k=n/2,将下标差值为k的书分为一组,构成有序序列。
2. 再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。
3. 重复第二步,直到k=1执行简单插入排序。

//希尔排序
template <typename T>
void Shell_Sort(T *arrayT, size_t length)
{int d  = length;while (d!=0){d=d/2;for (int x = 0; x < d; x++)  //分的组数{for (int i = x + d; i < length; i += d)  //组中的元素,从第二个数开始{int j = i - d;//j为有序序列最后一位的位数int temp = arrayT[i];//要插入的元素while(j >= 0 && temp < arrayT[j])//从后往前遍历。{arrayT[j + d] = arrayT[j];//向后移动d位j -= d;}arrayT[j + d] = temp;}}}
}

鸡尾酒排序-双向冒泡排序

鸡尾酒排序等于是冒泡排序的轻微变形。不同的地方在于从低到高然后从高到低,而冒泡排序则仅从低到高去比较序列里的每个元素。他可以得到比冒泡排序稍微好一点的效能,原因是冒泡排序只从一个方向进行比对(由低到高),每次循环只移动一个项目。

1、依次比较相邻的两个数,将小数放在前面,大数放在后面;
2、第一趟可得到:将最小数放到第一位。
3、第二趟可得到:将最大的数放到最后一位。
4、如此下去,重复以上过程,直至最终完成排序。
鸡尾酒排序最糟或是平均所花费的次数都是O(n^2),但如果序列在一开始已经大部分排序过的话,会接近O(n)。
最差时间复杂度 O(n^2)
最优时间复杂度 O(n)
平均时间复杂度 O(n^2)

//鸡尾酒排序--双向冒泡排序
template <typename T>
void Cocktail_Sort(T *arrayT, size_t length)
{int tail=length-1;int temp=0;for (int i=0; i<tail;){for (int j=tail; j>i; --j) //第一轮,先将最小的数据排到前面{if (arrayT[j]<arrayT[j-1]){temp=arrayT[j];arrayT[j]=arrayT[j-1];arrayT[j-1]=temp;}}++i;                    //原来i处数据已排好序,加1for (int j=i; j<tail; ++j)  //第二轮,将最大的数据排到后面{if (arrayT[j]>arrayT[j+1]){temp=arrayT[j];arrayT[j]=arrayT[j+1];arrayT[j+1]=temp;}}tail--;                 //原tail处数据也已排好序,将其减1}
}

堆排序

我们这里提到的堆一般都指的是二叉堆,它满足二个特性:
1—父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2—每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
如下为一个最小堆(父结点的键值总是小于任何一个子节点的键值)

堆调整(Heap Adjust):这是为了保持堆的特性而做的一个操作。对某一个节点为根的子树做堆调整,其实就是将该根节点进行“下沉”操作(具体是通过和子节点交换完成的),一直下沉到合适的位置,使得刚才的子树满足堆的性质。

例如对最大堆的堆调整我们会这么做:
1、在对应的数组元素A[i], 左孩子A[LEFT(i)], 和右孩子A[RIGHT(i)]中找到最大的那一个,将其下标存储在largest中。
2、如果A[i]已经就是最大的元素,则程序直接结束。
3、否则,i的某个子结点为最大的元素,将A[largest]与A[i]交换。
4、再从交换的子节点开始,重复1,2,3步,直至叶子节点,算完成一次堆调整。

这里需要提一下的是,一般做一次堆调整的时间复杂度为log(n)。

//------------------------------堆排序
/*返回父节点*/
inline int parent(int i)
{return (int)floor((i - 1) / 2);
}
/*返回左孩子节点*/
inline int left(int i)
{return (2 * i + 1);
}
/*返回右孩子节点*/
inline int right(int i)
{return (2 * i + 2);
}
/*对以某一节点为根的子树做堆调整(保证最大堆性质)*/
template <typename T>
void HeapAdjust(T A[], int i, int heap_size)
{int l = left(i);int r = right(i);int largest;int temp;//左孩子  层间顺序调动if(l < heap_size && A[l] > A[i]){largest = l;}else{largest = i;}//右孩子  层内顺序调动if(r < heap_size && A[r] > A[largest]){largest = r;}//是否交换if(largest != i){temp = A[i];A[i] = A[largest];A[largest] = temp;HeapAdjust(A, largest, heap_size);}
}/*建立最大堆*/
template <typename T>
void BuildHeap(T A[],int heap_size)
{//倒着建堆for(int i = (heap_size-2)/2; i >= 0; i--){HeapAdjust(A, i, heap_size);}
}
/*堆排序*/
template <typename T>
void HeapSort(T A[], int heap_size)
{BuildHeap(A, heap_size);int temp;//因为是大根堆,所以A[0]是堆顶元素是最大的,倒着放在最后,这样就是从小到大for(int i = heap_size - 1; i >= 0; i--){temp = A[0];A[0] = A[i];A[i] = temp;HeapAdjust(A, 0, i);//找到当前的最大值}
}

桶排序

(数有多大桶就有多大,好痛苦)
桶排序的思想就是这里有一个数量为Size个数的数组A,数组的值范围为(0 - Max)

这样我们可以创建一个大小为Max+1的数组B,每个元素都为0.

从头遍历A,当读取到A[i]的时候,B[A[i]]的值+1,这样所有的A数组被遍历后,直接扫描B之后,输出表B就可以了。

同理,为负数建立一个数组,然后倒着查找即可实现整数的排序。

//桶排序
template <typename T>
void Bucket_Sort(T *A, int Max, int Size)
{int B[Max+1];//正数的桶int M[Max+1];//负数的桶int i,j,count = 0;//初始化for (int k = 0; k <= Max; ++k){B[k] = 0;M[k] = 0;}//计数for (i = 0; i < Size; ++i){j = A[i];if(j>=0){B[j] += 1;}else{j=-j;M[j] += 1;}}//排序后的数组//负数for (i = Max; i >0; --i){if (M[i] > 0){for (j = 0; j < M[i]; ++j)//输出个数{A[count] = -i;count++;}}}//正数for (i = 0; i <= Max; ++i){if (B[i] > 0){for (j = 0; j < B[i]; ++j){A[count] = i;count++;}}}
}

基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

1、将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。
                2、从最低位开始,依次进行一次排序。
                3、这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

//基数排序
template <typename T>
void display1D(vector<T> &result)
{typename vector<T>::iterator iter;for(iter=result.begin(); iter!=result.end(); ++iter){cout<<(*iter)<<"\t";}cout<<endl;
}
//输出内容
template <typename T>
void display2D(vector<vector<T>> &result)
{//使用迭代器typename vector<vector<T>>::iterator iterAll;typename vector<T>::iterator iter;for( iterAll=result.begin(); iterAll!=result.end(); ++iterAll){for(iter=(*iterAll).begin(); iter!=(*iterAll).end(); ++iter){cout<<(*iter)<<"\t";}cout<<endl;}/*   已知数组容量for( int i=0; i<result.size(); ++i){for(int j=0; j<result.at(i).size(); ++j){cout<<result.at(i).at(j)<<"\t";}cout<<endl;}*/
}
//找到最大的数值
template <typename T>
int findMax(vector<T> &result)
{typename vector<T>::iterator iter=result.begin();int temp=(*iter);for(iter=result.begin(); iter!=result.end(); ++iter){if(temp<(*iter)){temp=(*iter);}}return temp;
}
//排序的次数
int getNumberOfSort(int number,int radix)
{int counter=0;//初始化while(number/radix){counter++;number/=radix;}return counter;
}
//一个二维的向量初始化
template <typename T>
void initialRadixVector(vector<vector<T>> &vectorAll,int radix)
{for(int i=0; i<radix; ++i){vector<T> temp;vectorAll.push_back(temp);}
}
//源复制到目的向量中
template <typename T>
void getVector(vector<T> &dest,vector<vector<T>> &source)
{dest.clear();//清空源向量typename vector<vector<T>>::iterator iterAll;typename vector<T>::iterator iter;typename vector<T>::reverse_iterator riter;//遍历得到新的向量for( iterAll=source.begin(); iterAll!=source.end(); ++iterAll){vector<int> temp;bool isMinus=false;for(iter=(*iterAll).begin(); iter!=(*iterAll).end(); ++iter){if(*iter>=0){dest.push_back(*iter);}else{isMinus=true;temp.push_back(*iter);}}if(isMinus)//负数需要倒着输出{for(riter=temp.rbegin(); riter!=temp.rend(); ++riter){dest.insert(dest.begin(),*riter);}temp.clear();}}
}//向量放在各个基数内
template <typename T>
void SetRadix(vector<vector<T>> &vectorAll,vector<T> &vect,int number,int radix)
{int location=0;//记录位置typename vector<vector<T>>::iterator iterAll;typename vector<T>::iterator iter;for(iter=vect.begin(); iter!=vect.end(); ++iter){location = abs(static_cast<int>(abs(*iter))/pow(radix,number))%(radix);vectorAll.at(location).push_back(*iter);}
}
//基数排序  ---   一次排序的过程
template <typename T>
void radixSortOnce(vector<T> &vect, int number,int radix)
{//初始化向量vector<vector<T>> vectorAll;//基数排序的基//初始化向量表initialRadixVector(vectorAll,radix);//将向量放在各个基数内SetRadix(vectorAll,vect,number,radix);//复制到临时变量中getVector(vect,vectorAll);//显示每次排序的过程//display1D(vect);//cout<<endl;
}
//基数排序
template <typename T>
void radixSort(vector<T> &vect, int number,int radix)
{if(0<=number){radixSort(vect,number-1,radix);radixSortOnce(vect,number,radix);}// end of if
}

全文的代码放在这里了大家来找BUG呀!
戳我—带你去整个代码的地方,欢迎来给我找BUG
测试环境 CodeBlocks 16.01

Reading List
寒小阳
JS家的排序算法
一遍记住Java常用的八种排序算法与代码实现

常用排序算法二 希尔-鸡尾酒-堆-桶-基数排序(C++)相关推荐

  1. 常用排序算法(二)快速排序

    快速排序 概要 本章介绍排序算法中的快速排序. 目录 1. 快速排序介绍 2. 快速排序图文说明 3. 快速排序的时间复杂度和稳定性 4. 快速排序实现 4.1 快速排序C实现 4.2 快速排序C++ ...

  2. 常见的排序算法二——希尔排序

    原理:被称为增量缩小排序.先将序列按增量划分为元素个数相同的若干组, 使用直接插入排序法进行排序,然后不断缩小增量直至为1, 最后使用直接插入排序完成排序. 要点:增量的选择以及排序最终以1为增量进行 ...

  3. 常用排序算法的c++实现(冒泡,选择,插入,堆,shell,快速,归并 )与sort()对比 - coder_xia的专栏 - 博客频道 - CSDN.NET...

    常用排序算法的c++实现(冒泡,选择,插入,堆,shell,快速,归并 )与sort()对比 - coder_xia的专栏 - 博客频道 - CSDN.NET 常用排序算法的c++实现(冒泡,选择,插 ...

  4. 机器学习(二十二)——推荐算法中的常用排序算法, Tri-training

    推荐算法中的常用排序算法 Pointwise方法 Pranking (NIPS 2002), OAP-BPM (EMCL 2003), Ranking with Large Margin Princi ...

  5. 常用排序算法复杂度分析

    1.排序大类 排序算法大致可以分为两大类:内部排序和外部排序.内部排序指的是排序数据都存储在内存中.外部排序则需要借助到外出.常用排序算法都为内部排序. 2.内部排序分类 (1)插入排序:直接插入排序 ...

  6. 常用排序算法 - 稳定性和复杂度分析

    一.前言 上一篇,只是简单的记录了常用算法的主要思想以及代码实现( 常用算法记录 ); 这次简单的记录一下算法的稳定性以及复杂度 二.稳定性 1. 稳定性的定义 如果两个相等的数据的先后位置,排序前后 ...

  7. 视觉直观感受7种常用排序算法

    视觉直观感受若干常用排序算法 1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状 ...

  8. java实现apriori算法_七大经典、常用排序算法的原理、Java 实现以及算法分析

    0. 前言 大家好,我是多选参数的程序员,一个正再 neng 操作系统.学数据结构和算法以及 Java 的硬核菜鸡.数据结构和算法是我准备新开的坑,主要是因为自己再这块确实很弱,需要大补(残废了一般) ...

  9. 常用排序算法总结(C语言版)

    文章目录 一.排序算法概览 二.算法实现 1.选择排序 2.冒泡排序 3.插入排序 4.快速排序 5.希尔排序 6.桶排序(基数排序) 7.归并排序 8.堆排序 三.总结 一.排序算法概览 可以在Vi ...

最新文章

  1. Nature年度十大杰出论文公布:机器狗算法、近室温超导等入选,复旦中科院上榜...
  2. Ubuntu16.04下arm-linux-gcc交叉编译环境搭建
  3. Matlab中巧用LaTex
  4. 简约代码表白_JS实现520 表白简单代码
  5. tar压缩解压缩命令详解
  6. h5应用 vue 钉钉_uniapp开发一个小视频应用(一)
  7. Linux expr命令、Linux wc命令、Linux let 命令
  8. 网页制作之CSS超级技巧
  9. python线程监控_Python 使用摄像头监测心率!这么强吗?
  10. 安卓车机没有ADB调试,任意安装第三方软件教程
  11. java管理系统类似的_开发类似安居客OA系统管理平台
  12. batchplot放到哪个文件夹_Batchplot(CAD批量打印工具)下载
  13. 2015款java 650b duina_整车推荐:9款5000元级别热销山地车
  14. 阿里云云计算ACP学习(二)---弹性存储
  15. 300句子与7000单词
  16. maven、md5、git学习
  17. nor flash原理详细讲解
  18. 谈谈反爬虫“政策与对策”
  19. 计算机用户被停用,电脑教程:Windows7用户被停用解决方法
  20. 厦理OJ——1003:第三届程序设计大赛 让气球飞起来

热门文章

  1. swing中通过.class文件(把.java都删除)打包成jar文件,使用皮肤包遇到的问题。
  2. 光通量、照度、光强度、亮度、辐射度、色彩还原的概念
  3. Python卸载时发生严重错误
  4. 常见充值方式介绍及对比 (转)
  5. 饿了么(elementUI)组件库如何在vue项目中使用?
  6. ubuntu进去安全模式_win10和Ubuntu双系统,无法开机如何进入win10安全模式
  7. 市场经济下的“按劳分配”
  8. pngquant图片压缩工具
  9. 陈凯歌: 大创意大《无极》
  10. linux 文件转utf 8,在Linux系统下把文件转换为UTF-8编码