Algorithm——1.排序.md
排序算法
交换类排序:冒泡排序、快速排序
选择类排序:简单选择排序、堆排序
插入类排序:直接插入排序、希尔排序
归并类排序:归并排序递归实现与非递归实现
交换类排序
交换类排序:冒泡排序、快速排序
冒泡排序
冒泡排序(Bubble Sort),排序的基本思想为两两比较小相邻数据的关键字,如果顺序为反则进行交换,直到没有反序的记录为止。
冒泡排序有多种变化,其三种不同实现的代码如下:
//OS:Win | Terminal:Cmder | Editor:Atom | Language:cvoid Swap(int *a , int *b){int temp = *a;*a = *b;*b = temp;
}//最容易的排序,从第一个元素开始向后与每一个元素进行比较,交换得到最小的元素,放在第i个位置
//这样排序进行较多次无用的比较,当然,这并不是所谓的冒泡排序
void SimpleBubble(int array[] , int length){for(int i = 0 ; i < length ; i++){for(int j = i+1 ; j < length ; j++){if(array[i] > array[j]){Swap(&array[i],&array[j]);}}}
}//从第一个位置开始,由下往上两两元素进行比较,判断并交换得到最小值
//这样排序依次循环确定第i个位置的元素
void LittleBubble(int array[] ,int length){for(int i =0 ; i < length ; i++){for(int j = length -1 ; j > i ;j --){if(array[j] < array[j-1]){Swap(&array[j],&array[j-1]);}}}
}//增加标志位isSwap来表示是否存在反序或者是否进行过交换操作
//直到序列没有反序记录为止
void BubbleSort(int array[] , int length){int isSwap = 1;for(int i = 0 ; i < length ; i ++){if(isSwap){isSwap = 0;for(int j = length -1 ; j > i ; j --){if(array[j] < array[j-1]){Swap(&array[j],&array[j-1]);isSwap = 1;}}}}
}void Print(int array[] , int length){for (int i = 0 ; i < length ;i++){printf(" %d",array[i]);}
}int main(){int array[] = {6,5,3,1,0,2,9,8,4,7};BubbleSort(array,10);Print(array,10);return 0;
}
快速排序
快速排序(Quick Sort)是在实践中最快的已知排序算法,平均运行时间是O(N log N)。快速排序之所以快是因为其精炼的、高度优化的内部循环。最坏情况的性能为O(N2),如今高度优化后的快速排序简单易懂并且不难证明。
和归并排序一样,快速排序也是一种分治的递归算法。
将数组array进行快速排序QuickSort的基本算法由以下简单的四步组成:
- 1.如果数组长度为0或者1,则直接返回;
- 2.使用Median3或其他方法获取枢纽元素pivot;
- 3.划分子集;
- 4.递归调用QuickSort
int Median3(int array[], int left , int right)
{int mid = (left+right)/2;if(array[left] > array[mid])Swap(&array[left],&array[mid]);if(array[left] > array[right])Swap(&array[left],&array[right]);if(array[mid] > array[right])Swap(&array[mid],&array[right]);//提前将mid位置元素放置合适位置Swap(&array[mid],&array[right-1]);return right-1;
}void Quick_Sort(int array[], int left , int right)
{if(left >= right)return;int pivot = Median3(array,left,right);int i = left , j = right-1;//Notice1:只有当i<j时才进入循环,i与j循环移动与pivot位置进行比较while(i<j){//Notice2:指示位置i所处元素与pivot处元素进行比较,如果小,则继续++向后移动;如果大,则跳出该次while循环while(array[++i] < array[pivot]){}//Notice3:指示位置j所处元素与pivot处元素进行比较,如果大,则继续--向前移动;如果小,则跳出该次while循环while(array[--j] > array[pivot]){}//Notice4:当i与j都跳出while循环时,比较i与j的大小,若i任然小于j,则交换两个位置的元素,再次进入外部while循环;如果i已经超过j位置,则直接breakif(i<j){Swap(&array[i],&array[j]);}else{break;}}//Notice5:交换i与pivot处元素,即确定该pivot处元素最终位置,已i位置为界完成此次子集划分Swap(&array[i],&array[pivot]);//Notice3:递归调用快速排序Quick_Sort(array,left,i-1);Quick_Sort(array,i+1,right);
}void QuickSort(int array[] , int length)
{Quick_Sort(array,0,length-1);
}
其中,Quick_Sort()中的外层while循环也可以写成for循环,代码如下:
void Quick_Sort(int array[] , int left ,int right){if(left >= right)return;int pivot = Median3(array,left,right);int i = left, j = right-1;for( ; ; ){if(i>=j)break;while(array[++i] < array[pivot]){}while(array[--j] > array[pivot]){}if(i<j)Swap(&array[i],&array[j]);elsebreak;}Swap(&array[i],&array[pivot]);Quick_Sort(array,left,i-1);Quick_Sort(array,i+1,right);
}
选择类排序
选择类排序:简单选择排序、堆排序
简单选择排序
简单选择排序(Simple Selection Sort),基本思想是:标记第i个元素为最小值下标min开始向后进行遍历比较,不断更新最小值下标min,结束该次循环后判断min是否改变,若改变即交换i位置元素及min位置的最小元素。
void SelectSort(int array[] , int length){int min;for(int i = 0 ; i <length ; i++){min = i ; //Notice1:以第一个元素为最小开始向后遍历比较for(int j = i+1 ; j < length ; j++){ //Notice2:j从i+1开始向后遍历if(array[j] < array[min]){ //Notice3:每次都是array[j]与array[min]进行比较,来确定和更新最小值所在下标min = j;}}if(min != i){Swap(&array[i] ,&array[min]);}}
}
堆排序
堆排序(Heap Sort)是一个非常稳定的算法,排序平均使用的比较只比最坏情况界指出的略少。
void AdjustHeap(int array[] , int i , int length){//Notice2:保存开始节点的值为temp,减少直接交换的次数int temp = array[i];for(int j = i*2 +1 ; j <length ; j = j*2+1){if(j+1 < length && array[j] < array[j+1])j++;if(array[j] < temp ) //Notice3:循环对temp中保存的值进行比较break;array[i] = array[j];i = j;}array[i] = temp; //Notice4:最后在temp合适的位置上进行赋值放置
}void HeapSort(int array[] ,int length){//Notice1:首先从最后一个非页子节点开始,由右向左、由下至上开始进行最大堆的构造for(int i = length/2 ; i >= 0 ; i --){AdjustHeap(array , i ,length);}for(int i = length -1 ; i > 0 ; i --){Swap(&array[0],&array[i]);AdjustHeap(array, 0, i );}
}
插入类排序
插入类排序:直接插入排序、希尔排序
直接插入排序
直接插入排序(Straight Insertion Sort)是最简单的排序算法之一,主要思想是保证位置0到第i-1位置上的元素为已排序状态,即插入排序利用这样的事实,从i位置循环进行排序。
void InsertionSort(int array[] , int length ){int i,j,temp;//Notice1:开始以第一个数据为有序序列,从第二个数据开始排序for(i = 1 ; i <length ; i++){if(array[i] < array[i-1]){ //Notice2:当当前数据大于前一个时,开始向前插入temp = array[i]; //保存此时的值,为前方较大元素空出位置for(j = i -1 ; j>=0 && array[j] > temp ; j--){ //向前循环直至下标小于0,或者值比当前值更小array[j+1] = array[j]; //依次后移}array[j+1] = temp; //此时j位置的元素小于当前值,所以插入其后一位j+1即可}}
}
希尔排序
希尔排序(Shell Sort)是冲破二次时间屏障的第一批算法之一。主要思想是:通过比较一定间隔的元素来工作;各趟比较所用的距离(希尔增量)随着算法的进行而逐渐减小,直到比较相元素的最后一趟排序为止。因此,希尔排序也称为缩小增量排序。
void ShellSort(int array[] , int length){int i,j,temp,gap;int judgeCount = 0, changeCount = 0;//Notice1:设置希尔增量序列初始值 gap = length/2 ,一直循环值gap=1进行最后一次插入排序for(gap = length/2 ; gap >0 ; gap /=2){//Notice2:内层嵌套一个直接插入循环for(i = gap ; i < length ; i++ ){judgeCount++;if(array[i] < array[i - gap]){temp = array[i];for(j = i - gap ; j >= 0 && array[j] > temp ; j -=gap){array[j+gap] = array[j];changeCount++;}array[j+gap] = temp;}}}printf("Judge Count : %d ,Change Count : %d .\n", judgeCount,changeCount);
}
归并类排序
归并类排序:归并排序递归实现与非递归实现。
当归并排序以O(NlogN)最坏情形运行时间运行时,而所使用的比较次数几乎是最优的。其核心算法Merge的基本操作为:合并两个已经有序的子列。
递归实现
//Notice1:归并排序的核心,两个有序子列的归并
void Merge(int array[] , int tmpArray[] , int l ,int r ,int rEnd )
{//Notice2:根据传入的参数得出所要归并的两个有序子列的总长度length、//左端有序子列起点l、终点lEnd、右端有序子列起点r、终点rEndint length = rEnd - l + 1;int lEnd = r -1;int temp = l;//Notice3:当同时满足左端指示位置 l <= lEnd、 右端指示位置 r <= rEnd 时,进入while循环//此处while循环判定条件为 <= ,当 = 时,进行该子列最后一个元素的比较while( l <= lEnd && r <= rEnd){//Notice4:此处判断条件为<=,当两个指示指针所指的两个子列中的元素相等时,保持其先后次序if(array[l] <= array[r]) tmpArray[temp++] = array[l++];else tmpArray[temp++] = array[r++];}while( l <= lEnd)tmpArray[temp++] = array[l++];while( r <= rEnd)tmpArray[temp++] = array[r++];for(int i = 0 ; i < length ; i++ , rEnd--){array[rEnd] = tmpArray[rEnd];}
}void Merge_Sort(int array[] ,int tmpArray[] , int l ,int rEnd )
{int mid;if( l < rEnd){mid = (l + rEnd)/2;Merge_Sort(array,tmpArray,l,mid);Merge_Sort(array,tmpArray,mid+1,rEnd);Merge(array,tmpArray,l,mid+1,rEnd);}
}void MergeSort(int array[] , int length)
{int tmpArray[length];Merge_Sort(array,tmpArray,0,length-1);free(tmpArray);
}
非递归实现
//Notice1:归并排序的核心,合并两个有序子列
void Merge(int array[] , int tmpArray[] , int l , int r, int rEnd)
{int length = rEnd - l + 1;int lEnd = r - 1;int temp = l;while( l <= lEnd && r <= rEnd){if(array[l] < array[r]) tmpArray[temp++] = array[l++];else tmpArray[temp++] = array[r++];}while( l <= lEnd)tmpArray[temp++] = array[l++];while( r <= rEnd)tmpArray[temp++] = array[r++];for(int i = 0 ; i < length ; i++ , rEnd--){array[rEnd] = tmpArray[rEnd];}
}//Notice2:对子列长度为gap时的一轮完整归并
void Merge_Pass(int array[] , int tmpArray[] , int length , int gap)
{int i,j;for(i = 0 ; i <= length - gap*2 ; i += gap*2)Merge(array,tmpArray, i , i+gap , i + gap*2 -1);if(i+gap < length)Merge(array,tmpArray,i,i+gap,length-1);elsefor(j = i ; j < length ;j++)tmpArray[j] = array[j];
}//Notice3:当子列长度gap<length时,进行一轮完整归并,并保证排好序的序列赋值到原数组
void MergeSort(int array[] ,int length)
{int gap = 1;int tmpArray[length];while(gap < length){Merge_Pass(array,tmpArray,length,gap);gap *= 2;Merge_Pass(tmpArray,array,length,gap);gap *= 2;}free(tmpArray);
}
REF
书籍:
数据结构与算法分析、大话数据结构
转载于:https://www.cnblogs.com/sylvan/p/9383107.html
Algorithm——1.排序.md相关推荐
- algorithm -- 选择排序
选择排序是<导论>第一章课后习题,仿照插入排序,再次运用循环不变式来证明下算法的正确性,C++ 源码: // 交换函数 void swap( int& a, int& b ...
- LeetCode Algorithm 148. 排序链表
148. 排序链表 Ideas 链表结构的经典题目. 不过我不想用经典方法做,哎,就是皮. 我把链表元素都拷贝到数组中,然后对数组排序,之后再把排完序之后的值赋回去. 骚的一批. Code Pytho ...
- 排序算法,最全的10大排序算法详解(Sort Algorithm)
文章目录 排序算法,最全的10大排序算法详解(Sort Algorithm) 排序算法分类 排序算法稳定性 时间复杂度(time complexity) 1#时间复杂度的意义 2#基本操作执行次数 如 ...
- java python算法_用Python,Java和C ++示例解释的排序算法
java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...
- 【基础算法】算法,从排序学起(一)
本文目录 1.导言 2.谈谈排序 2.1 何为排序?(What is sorting?) 2.2 排序的应用(Why sorting?) 2.3 常见排序算法的种类(How to sort?) 3.基 ...
- 排序方法分析与代码实现
排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程.鉴于经常面试中需要考察本方面的内容,也为了后期及时复习相关知识,故在此将算法相关知识系列进行总结记录,以 ...
- 教小学妹学算法:十大经典排序算法深度解析
最近有一位小学妹 Coco 入坑了算法,结果上来就被几个排序算法给整懵逼了,各种排序眼花缭乱,也分不清什么时候该用什么排序了. 今天呢,就在这分享一下我给小学妹讲十大经典排序算法的过程. 好吧,那我们 ...
- js 实现2的n次方计算函数_JS中数据结构与算法---排序算法
排序算法的介绍 排序也称排序算法 (Sort Algorithm),排序是将 一组数据 , 依指定的顺序 进行 排列的过程 . 排序的分类 内部排序 : 指将需要处理的所有数据都加载 到 内部存储器( ...
- 最大子数组问题 线性时间_我最喜欢的线性时间排序算法
最大子数组问题 线性时间 by Franziska Hinkelmann 通过Franziska Hinkelmann 我最喜欢的线性时间排序算法 (My Favorite Linear-time S ...
最新文章
- linux命令:groupadd
- Spring Boot(四)Accessing application arguments
- 干货!MySQL 资源大全
- linux安装apache的纠结过程
- 程序员的选房神技,GitHub上的房源爬虫
- 高性能计算机 和服务器,一种高性能计算机服务器
- Web中树形数据(层级关系数据)的实现—以行政区树为例
- 安卓逆向系列教程(三)静态分析工具
- 存储引擎和Mysql服务层出现索引信息不一致错误提示
- 莫烦Tensorflow教程(1~14)(转)
- Repeater OnItemCommand 失效
- 使用Linq作为rdlc报表的数据源
- 什么录播软件好用?超级好用的录屏软件在这里
- 如何使用keil 5 编写 51单片机 工程
- 3dmax 模型导出单位设置问题
- 开根号的笔算算法图解_excel中开根号的计算方法步骤详解
- 用免费WiFi上网软件有什么好处
- 坚持你的梦想,什么时候都不晚!
- Graph Stacked Hourglass Networks for 3D Human Pose Estimation
- Mac 下 unrar 命令
热门文章
- Sql Server 2005中的快照隔离
- 幂等问题-概念上的通俗解释(未完待续)
- SecureCRT连接CentOS阿里云,小键盘在VIM情况下,无法输入数字反而出现英文
- 屏幕输出语句_第三章 常用输入/输出函数
- 机器学习(二十九)——Temporal-Difference Learning
- python自动写作软件_有哪些适合长文的轻量级写作软件值得推荐?
- 引用一个项目作为library的操作步骤---开发中遇到的问题(二)
- Linux基础命令---apachectl
- ES6-note-Set和Map(草稿)
- ConstraintLayout如何优化布局性能