常用的五大排序总结

冒泡排序

一. 算法描述

冒泡排序:依次比较相邻的数据,将小数据放在前,大数据放在后;即第一趟先比较第1个和第2个数,大数在后,小数在前,再比较第2个数与第3个数,大数在后,小数在前,以此类推则将最大的数"滚动"到最后一个位置;第二趟则将次大的数滚动到倒数第二个位置......第n-1(n为无序数据的个数)趟即能完成排序。

以下面5个无序的数据为例:

40 8 15 18 12 (文中仅细化了第一趟的比较过程)

第1趟: 8 15 18 12 40

第2趟: 8 15 12 18 40

第3趟: 8 12 15 18 40

第4趟: 8 12 15 18 40

二. 算法分析

平均时间复杂度:O(n2)

空间复杂度:O(1)  (用于交换)

稳定性:稳定

三. 算法实现

//交换data1和data2所指向的整形  voidDataSwap(int* data1,int* data2){inttemp = *data1;      *data1 = *data2;      *data2 = temp;  }/********************************************************

*函数名称:BubbleSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    冒泡排序

*********************************************************/voidBubbleSort(int* pDataArray,intiDataNum){for(inti =0; i < iDataNum -1; i++)//走iDataNum-1趟  for(intj =0; j < iDataNum - i -1; j++)if(pDataArray[j] > pDataArray[j +1])                  DataSwap(&pDataArray[j], &pDataArray[j +1]);  }

四. 算法优化

还可以对冒泡排序算法进行简单的优化,用一个标记来记录在一趟的比较过程中是否存在交换,如果不存在交换则整个数组已经有序退出排序过程,反之则继续进行下一趟的比较。

/********************************************************

*函数名称:BubbleSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    冒泡排序

*********************************************************/voidBubbleSort(int* pDataArray,intiDataNum)  {BOOLflag =FALSE;//记录是否存在交换  for(inti =0; i < iDataNum -1; i++)//走iDataNum-1趟  {          flag =FALSE;for(intj =0; j < iDataNum - i -1; j++)if(pDataArray[j] > pDataArray[j +1])              {                  flag =TRUE;                  DataSwap(&pDataArray[j], &pDataArray[j +1]);              }if(!flag)//上一趟比较中不存在交换,则退出排序  break;      }  }

选择排序

一. 算法描述

选择排序:比如在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,至此选择排序完成。

以下面5个无序的数据为例:

56 12 80 91 20(文中仅细化了第一趟的选择过程)

第1趟:12 56 80 91 20

第2趟:12 20 80 91 56

第3趟:12 20 56 91 80

第4趟:12 20 56 80 91

二. 算法分析

平均时间复杂度:O(n2)

空间复杂度:O(1)  (用于交换和记录索引)

稳定性:不稳定 (比如序列【5, 5, 3】第一趟就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)

三. 算法实现

//交换data1和data2所指向的整形  voidDataSwap(int* data1,int* data2){inttemp = *data1;      *data1 = *data2;      *data2 = temp;  }/********************************************************

*函数名称:SelectionSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    选择排序

*********************************************************/voidSelectionSort(int* pDataArray,intiDataNum){for(inti =0; i < iDataNum -1; i++)//从第一个位置开始  {intindex = i;for(intj = i +1; j < iDataNum; j++)//寻找最小的数据索引  if(pDataArray[j] < pDataArray[index])                  index = j;if(index != i)//如果最小数位置变化则交换  DataSwap(&pDataArray[index], &pDataArray[i]);      }  }

插入排序

一. 算法描述

插入排序:插入即表示将一个新的数据插入到一个有序数组中,并继续保持有序。例如有一个长度为N的无序数组,进行N-1次的插入即能完成排序;第一次,数组第1个数认为是有序的数组,将数组第二个元素插入仅有1个有序的数组中;第二次,数组前两个元素组成有序的数组,将数组第三个元素插入由两个元素构成的有序数组中......第N-1次,数组前N-1个元素组成有序的数组,将数组的第N个元素插入由N-1个元素构成的有序数组中,则完成了整个插入排序。

以下面5个无序的数据为例:

65 27 59 64 58 (文中仅细化了第四次插入过程)

第1次插入: 27 65 59 64 58

第2次插入: 27 59 65 64 58

第3次插入: 27 59 64 65 58

第4次插入: 27 58 59 64 65

二. 算法分析

平均时间复杂度:O(n2)

空间复杂度:O(1)  (用于记录需要插入的数据)

稳定性:稳定

三. 算法实现

从前向后查找的插入排序:

/********************************************************

*函数名称:InsertSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    插入排序

*********************************************************/voidInsertSort(int* pDataArray,intiDataNum){for(inti =1; i < iDataNum; i++)//从第2个数据开始插入  {intj =0;while(j < i && pDataArray[j] <= pDataArray[i])//寻找插入的位置  j++;if(j < i)//i位置之前,有比pDataArray[i]大的数,则进行挪动和插入  {intk = i;inttemp = pDataArray[i];while(k > j)//挪动位置  {                  pDataArray[k] = pDataArray[k-1];                  k--;              }              pDataArray[k] = temp;//插入  }      }  }

但我发现从后面查找插入的方式,代码复杂程度较低:

/********************************************************

*函数名称:InsertSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    插入排序

*********************************************************/voidInsertSort(int* pDataArray,intiDataNum){for(inti =1; i < iDataNum; i++)//从第2个数据开始插入  {intj = i -1;inttemp = pDataArray[i];//记录要插入的数据  while(j >=0&& pDataArray[j] > temp)//从后向前,找到比其小的数的位置  {              pDataArray[j+1] = pDataArray[j];//向后挪动  j--;          }if(j != i -1)//存在比其小的数  pDataArray[j+1] = temp;      }  }

四. 算法优化

插入排序中,总是先寻找插入位置,然后在实行挪动和插入过程;寻找插入位置采用顺序查找的方式(从前向后或者从后向前),既然需要插入的数组已经是有序的,那么可以采用二分查找方法来寻找插入位置,提高算法效率,但算法的时间复杂度仍为O(n2)。

//查找数值iData在长度为iLen的pDataArray数组中的插入位置  intFindInsertIndex(int*pDataArray,intiLen,intiData){intiBegin =0;intiEnd = iLen -1;intindex =-1;//记录插入位置  while(iBegin <= iEnd)      {          index = (iBegin + iEnd) /2;if(pDataArray[index] > iData)              iEnd = index -1;elseiBegin = index +1;      }if(pDataArray[index] <= iData)          index++;returnindex;  }/********************************************************

*函数名称:BinaryInsertSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    二分查找插入排序

*********************************************************/voidBinaryInsertSort(int* pDataArray,intiDataNum){for(inti =1; i < iDataNum; i++)//从第2个数据开始插入  {intindex = FindInsertIndex(pDataArray, i, pDataArray[i]);//二分寻找插入的位置  if(i != index)//插入位置不为i,才挪动、插入  {intj = i;inttemp = pDataArray[i];while(j > index)//挪动位置  {                  pDataArray[j] = pDataArray[j-1];                  j--;              }              pDataArray[j] = temp;//插入  }      }  }

快速排序

一. 算法描述

快速排序:快速排序采用分治法进行排序,首先是分割,选取数组中的任意一个元素value(默认选用第一个),将数组划分为两段,前一段小于value,后一段大于value;然后再分别对前半段和后半段进行递归快速排序。其实现细节如下图所示:

二. 算法分析

平均时间复杂度:O(nlog2n)

空间复杂度:O(n)

稳定性:不稳定

三. 算法实现

/********************************************************

*函数名称:Split

*参数说明:pDataArray 无序数组;

*          iBegin为pDataArray需要快速排序的起始位置

*          iEnd为pDataArray需要快速排序的结束位置

*函数返回:分割后的分割数位置

*说明:    以iBegin处的数值value作为分割数,

          使其前半段小于value,后半段大于value

*********************************************************/intSplit(int*pDataArray,intiBegin,intiEnd){intpData = pDataArray[iBegin];//将iBegin处的值作为划分值  while(iBegin < iEnd)//循环分割数组,使其前半段小于pData,后半段大于pData  {while(iEnd > iBegin && pDataArray[iEnd] >= pData)//从后向前寻找小于pData的数据位置  iEnd--;if(iEnd != iBegin)          {              pDataArray[iBegin] = pDataArray[iEnd];//将小于pData数据存放到数组前方  iBegin++;while(iBegin < iEnd && pDataArray[iBegin] <= pData)                  iBegin++;if(iBegin != iEnd)              {                  pDataArray[iEnd] = pDataArray[iBegin];//将大于pData数据存放到数组后方  iEnd--;              }          }      }        pDataArray[iEnd] = pData;//此时iBegin=iEnd,此处存储分割数据pData  returniEnd;  }/********************************************************

*函数名称:QSort

*参数说明:pDataArray 无序数组;

*          iBegin为pDataArray需要快速排序的起始位置

*          iEnd为pDataArray需要快速排序的结束位置

*说明:    快速排序递归函数

*********************************************************/voidQSort(int* pDataArray,intiBegin,intiEnd){if(iBegin < iEnd)      {intpos = Split(pDataArray, iBegin, iEnd);//获得分割后的位置  QSort(pDataArray, iBegin, pos -1);//对分割后的前半段递归快排  QSort(pDataArray, pos +1, iEnd);//对分割后的后半段递归快排  }  }/********************************************************

*函数名称:QuickSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    快速排序

*********************************************************/voidQuickSort(int* pDataArray,intiDataNum){      QSort(pDataArray,0, iDataNum -1);  }

四. 算法优化

快排选用数组第一个元素作为分割元素,如果是一个已经基本有序的数组,那么时间复杂度将会提升到O(n2);可以从数组中随机选择一个元素作为划分数据,这样即使针对基本有序的数据来说,效率同样达到(nlog2n),优化后分割函数如下所示:

intSplit(int*pDataArray,intiBegin,intiEnd){intrIndex = rand() % (iEnd - iBegin +1);//随机获得偏移位置  intpData = pDataArray[iBegin + rIndex];//将iBegin+rIndex处的值作为划分值  while(iBegin < iEnd)//循环分割数组,使其前半段小于pData,后半段大于pData  {while(iEnd > iBegin && pDataArray[iEnd] >= pData)//从后向前寻找小于pData的数据位置  iEnd--;if(iEnd != iBegin)          {              pDataArray[iBegin] = pDataArray[iEnd];//将小于pData数据存放到数组前方  iBegin++;while(iBegin < iEnd && pDataArray[iBegin] <= pData)                  iBegin++;if(iBegin != iEnd)              {                  pDataArray[iEnd] = pDataArray[iBegin];//将大于pData数据存放到数组后方  iEnd--;              }          }      }        pDataArray[iEnd] = pData;//此时iBegin=iEnd,此处存储分割数据pData  returniEnd;  }

希尔排序

一. 算法描述

希尔排序:将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序;然后再选择一个更小的增量,再将数组分割为多个子序列进行排序......最后选择增量为1,即使用直接插入排序,使最终数组成为有序。

增量的选择:在每趟的排序过程都有一个增量,至少满足一个规则 增量关系 d[1] > d[2] > d[3] >..> d[t] = 1 (t趟排序);根据增量序列的选取其时间复杂度也会有变化,这个不少论文进行了研究,在此处就不再深究;本文采用首选增量为n/2,以此递推,每次增量为原先的1/2,直到增量为1;

下图详细讲解了一次希尔排序的过程:

二. 算法分析

平均时间复杂度:希尔排序的时间复杂度和其增量序列有关系,这涉及到数学上尚未解决的难题;不过在某些序列中复杂度可以为O(n1.3);

空间复杂度:O(1)

稳定性:不稳定

三. 算法实现

/********************************************************

*函数名称:ShellInsert

*参数说明:pDataArray 无序数组;

*          d          增量大小

*          iDataNum为无序数据个数

*说明:    希尔按增量d的插入排序

*********************************************************/voidShellInsert(int* pDataArray,intd,intiDataNum){for(inti = d; i < iDataNum; i +=1)//从第2个数据开始插入  {intj = i - d;inttemp = pDataArray[i];//记录要插入的数据  while(j >=0&& pDataArray[j] > temp)//从后向前,找到比其小的数的位置  {              pDataArray[j+d] = pDataArray[j];//向后挪动  j -= d;          }if(j != i - d)//存在比其小的数  pDataArray[j+d] = temp;      }  }/********************************************************

*函数名称:ShellSort

*参数说明:pDataArray 无序数组;

*          iDataNum为无序数据个数

*说明:    希尔排序

*********************************************************/voidShellSort(int* pDataArray,intiDataNum){intd = iDataNum /2;//初始增量设为数组长度的一半  while(d >=1)      {          ShellInsert(pDataArray, d, iDataNum);          d = d /2;//每次增量变为上次的二分之一  }  }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • 总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序...
    jiangliang阅读 1,334评论 0 1
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,421评论 1 4
  • 初夏里看的是蔡澜三部曲,应该是他历年专栏整理而来,一则则短篇,早起晚睡时读一读,茶余饭后读一读,不费脑筋,得些欢欣...
    mosquito呀阅读 165评论 0 0
  • 可能每个人的人体组成都不一样吧,不然为什么会出现黑心红心的人那。
    醣丝zx阅读 144评论 0 2
  • 期中考试和期末考试一样重要,有时还意义非凡。考好了,心里甜滋滋的,随之而来的是老师的赞扬、同学们的羡慕和父...
    绽放的微笑yf阅读 398评论 0 0