排序算法总结
来源:互联网 发布:wamp怎么运行php 编辑:程序博客网 时间:2024/06/06 12:41
只讨论内部排序算法:
1.比较排序,时间复杂度O(nlogn)~O(n^2)有:冒泡排序。选择排序,插入排序,归并排序,堆排序,快速排序
2.非比较排序,时间复杂度可以达到O(n),主要有:计数排序,基数排序,桶排序
排序算法的性能:
排序算法的稳定性:
可以简单定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称为这种排序算法是稳定的。也就是保证排序前后两个相等的数的相对顺序不变。排序算法的好处是:排序算法如果是稳定的,那么从一个键上排序。然后再从另一个键上排序,前一个键排序的结果可以为后一个键排序所用
冒泡排序:
冒泡排序是一种很简单的排序的算法,它重复走访过要排序的元素,依次比较相邻两个元素,如果它们的顺序错误就把它们调换过来,直到没有元素再需要交换,排序完成。
原理如下:
1.比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
2.对每一对相邻元素同样的工作,从开始第一队到结尾的最后一对。这捕做完,最后的元素会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越小的元素重复上面的步骤,直到没有任何一对数字需要比较。
代码:
void sort(int sort[]){for(int j=0;j<sort.length()-1;j++){//每次最大的元素排到数组最后 for(int i=0;i<sort.length()-1-j;i++){//依次比较相邻的两个元素 if(A[i])>A[i+1]{//交换 swaf(A,i,i+1); } } }}改进:设置一标志性变量pos,用于记录每趟排序最后一次进行交换的位置,由于pos位置之后的记录均已交换到位,故在进行下一趟排序只要扫描到pos位置即可。
void sort2(int sort2[]){ int i = sort2.length()-1;//初始时,最后位置保持不变 while(i>0){ int pos = 0;//每趟开始,无记录交换 for(int j = 0;j<i;j++){ if(sort2[j] > sort2[j+1]){ pos = j;//记录交换位置 swaf(sort,j,j+1); } i =pos;//为下一趟排序做准备 } }}再改进:鸡尾酒排序
此算法和冒泡排序的不同处在于从低到高然后从高到低,而冒泡排序则仅从低到高去比较序列里的每个元素,可以得到比冒泡排序稍微好一点的效能。
void sort3(int A[], int n){ int left = 0;//初始化边界 int right = n-1; while(left < right){ for(int i = left;i < right; i++){//前半轮,将最大元素放到最后 if(A[i] > A[i+1]){ swap(A,i,i+1); } } right--; for(int i =right;i>left;i--){ if(A[i-1]>A[i]){ swap(A,i-1.i); } }left++}}
选择排序:
选择排序是一种简单直观的排序算法,它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放在序列的起始位置作为排序;然后再从剩余排序元素中继续寻找最小(大)元素,放到已排序的末尾,以此类推,直到所有元素均排序完毕。选择排序和冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不合法的元素位置,从而将当前最小(大)元素放大合适的位置;选择排序每遍历一次都记住当前最小(大)元素的位置,最后仅需交换操作即可将其放到合适的位置。
void SelectSort(int A[],int n){ for(int i=0;i<n-1;i++){//i为已排序列的末尾 int min =i; for(int j = i+1;j< n;j++){//末排序序列 if(A[j]<A[min]){ //找出末排序序列中最小值 min = j; } if(min != i){ Swap(A,min,i)//放到已排序序列的末尾 } } }}
插入排序:
插入排序是一种简单直观的排序算法,工作原理类似于我们抓扑克牌
具体原理如下:
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后往前扫描
3.如果该元素大于新元素,将该元素移到下一个位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
6.重复步骤2-5
void insertsort(int A[],int n){ for(int i =1;i<n;i++){ int s = A[i]; int j= i-1; while(j>=0 && A[j]>s){ A[j+1] = A[j]; j--; } A[J+1] = s; } }改进后插入排序:二分插入排序,因为左边的数字总是排序好的,所以可以用二分排序来优化
void insertdichot(int A[],int n){ for(int i = 1;i<n;i++){ int get = A[i]; //右边的数 int left = 0; int right = i -1;//左右边边界初始化 while(left <= right){//采用二分定位新数 int mid = (left + right)/2 if(A[mid] > get){ right = mid -1; else left = mid + 1;}for(int j =i -1;j>=left;j--){//将欲插入新数位置右边的数整体向右移动一个单位 A[j+1] = A[j];}A[left] = get; }}}
归并排序:
归并排序的实现分为递归实现与非递归实现,递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题。然后用小问题的答案来解决整个大问题。非递归实现的归并排序首先是进行两两归并,然后四四归并,然后八八归并,一直下去直到并到整个数组。
归并操作步骤如下:
1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2.设定两个指针,最初位置分别为两个已经排序序列的起始位置
3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一个位置
4.重复步骤3直到某一指针到达序列尾
5.将另一序列剩下的所有元素直接复制到合并序列尾
void Merge(int A[],int left,int mid,int right){//合并两个已排好序的数组A[left...mid]和A[mid+1...right]int len = right - left +1;int *temp = new int[len];//辅助空间int index = 0;int i = left;//前一数组的起始元素int j=mid+1;//后一数组的起始元素while(i<mid && j<=right){ temp[index] = A[i] <=A[j] ? A[i++] :A[j++];}while(i <= mid){ temp[index++] = A[i++];}while(j <= right){ temp[index++] = A[j++];}for(int k = 0;k<len;K++){ A[left++] =temp[k];}}void MergeSortRecursion(int A[],int left,int right)//递归实现的归并排序{ if(left == right) return; int mid = (left + right)/2; MergeSortRecursion(A, left, mid); MergeSortRecursion(A, mid + 1, right); Merge(A, left, mid, right);}void MergeSortIteration(int A[], int len) // 非递归(迭代)实现的归并排序(自底向上){ int left, mid, right;// 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right] for (int i = 1; i < len; i *= 2) // 子数组的大小i初始为1,每轮翻倍 { left = 0; while (left + i < len) // 后一个子数组存在(需要归并) { mid = left + i - 1; right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够 Merge(A, left, mid, right); left = right + 1; // 前一个子数组索引向后移动 } }}
快速排序算法:
快速排序是对冒泡排序的一种改进,通过一趟排序将要排序的数据分割成独立的两个部分,其中一部分的所有数据都比另一部分的所有数据,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个暑假变成有序序列
一趟快速排序的算法是:
1.设置两个变量i,j,排序开始的时候:i=0;j=N-1;
2.以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3.从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]交换;
4.从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5.重复第3,4步直到i=j;(3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j,i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i,j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)
int Partition(int A[],int left,int right){ // 划分函数
int pivot = A[right]; //每次都选择最后一个元素作为基准
int tail = left -1;//tail为小于基准的子数组最后一个元素的索引
for(int i = left;i<right;i++){//遍历基准以外的其他元素
if(A[i]< = pivot){
swap(A,++tail,i);
}
}
swap(A,tail+1,right);//最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组
return tail +1;
void QuickSort(int A[]),int left,int right{
if(left >=right){
return;
int position = Partition(A,left,right);//基准的索引
QuickSort(A,left,position-1);
QuickSort(A.position+1,right);
}
}
}
希尔排序:
希尔排序是插入排序的一种,是直接插入排序算法的一种。
举个例子:
void shell(int a[]) int d=a.length; while(true) { d=d/2; for(int x=0;x<d;x++) { for(int i=x+d;i<a.length;i=i+d) { int temp=a[i]; int j; for(j=i-d;j>=0&&a[j]>temp;j=j-d) { a[j+d]=a[j]; } a[j+d]=temp; } } if(d==1) { break; } }}
排序算法很基础也很重要。也要注意每种算法所适合的场景。
阅读全文
0 0
- 算法--排序算法总结
- 算法:排序算法总结
- 算法:排序算法总结
- 算法-排序算法总结
- 算法-排序算法总结
- 【排序算法】排序算法总结
- 排序算法总结---希尔排序
- 排序算法总结---冒泡排序
- 排序算法总结----快速排序
- 排序算法总结---希尔排序
- 排序算法总结【内排序】
- 排序算法之内排序总结
- 排序算法总结:冒泡排序
- 【排序算法总结】冒泡排序
- 【排序算法总结】选择排序
- 排序算法总结
- 排序算法大总结
- 排序算法总结
- 第三章
- 多线程I
- 与别校的联hu考zuo(11.4)
- Qt 实现被鼠标悬浮的图片放大显示
- 设计模式(19)——观察者 Observer
- 排序算法总结
- JAVA字符串的操作
- 多线程II----thread类中的方法
- caffe的prototxt绘制
- Python编程之四书五经
- Zookeeper的局限性
- 【软考】之面向对象技术
- 习题6.1
- 算法---分解质因数