基础算法(排序)
来源:互联网 发布:php从入门到精通下载 编辑:程序博客网 时间:2024/06/07 16:23
1. 简单选择排序。
排序原理:每次选择数组中最小的元素放在数组开头,多次循环完成排序。
例如:数组 [3,7,2,9,3,1,0,6] 的排序过程:
[3 7 2 9 3 1 0 6]
[3 7 2 9 3 1 0 6](寻找最小元素)
[0 7 2 9 3 1 3 6](交换)
0 [7 2 9 3 1 3 6](寻找最小元素)
0 [1 2 9 3 7 3 6](交换)
… …
0 1 2 3 3 6 7 9
程序如下:
#include <stdio.h>#define INF 0xffff//输出数组void outputArray(int test[],int length){ int i; //printf("%d ",sizeof(test)/sizeof(int)); for(i=0;i<length;i++) { printf("%d ",test[i]); } printf("\n");}//交换两个数void swap_num(int &a,int &b){ int temp=b; b=a; a=temp;}//简单选择排序void simpleSort(int test[],int length){ int i,j; for(i=0;i<length-1;i++) { int min_j=i+1; for(j=i+1;j<length;j++) { if(test[j]<test[min_j]) { min_j=j; } } if(test[i]>test[min_j]) { swap_num(test[i],test[min_j]); } }}int main(){ int test[]={3,7,2,9,3,1,0,6}; int length=sizeof(test)/sizeof(int); printf("排序前:"); outputArray(test,length); printf("排序后:"); simpleSort(test,length); outputArray(test,length); return 0;}
复杂度分析:
由于使用了2个for循环,时间复杂度为O(n^2);排序的时候是在数组内部进行,空间复杂度为O(1)。由于是交换排序,所以排序过程是不稳定的。
2. 冒泡排序。
排序原理:依次比较两个相邻的元素,如果顺序不对就交换。重复以上步骤,直到没有可以交换的元素为止。
例如:数组 [3,7,2,9,3,1,0,6] 的排序过程:
[3 7 2 9 3 1 0 6]
[3 2 7 9 3 1 0 6]
[3 2 7 9 3 1 0 6]
[3 2 7 3 9 1 0 6]
[3 2 7 3 1 9 0 6]
[3 2 7 3 1 0 9 6]
[3 2 7 3 1 0 6 9](第一轮排序完成)
[2 3 3 1 0 6 7 9](第二轮排序完成)
[2 3 1 0 3 6 7 9](第三轮排序完成)
[2 1 0 3 3 6 7 9](第四轮排序完成)
[1 0 2 3 3 6 7 9](第五轮排序完成)
[0 1 2 3 3 6 7 9](第六轮排序完成)
程序如下:
//冒泡排序void bubbleSort(int test[],int length){ int flag=1,i; while(flag){ flag=0; for(i=0;i<length-1;i++){ if(test[i]>test[i+1]){ flag=1; swap_num(test[i],test[i+1]); } } //outputArray(test,length); }}
复杂度分析:
两层循环,时间复杂度O(n^2),空间复杂度O(1),由于冒泡排序始终保证小元素在大元素前面,所以是稳定的排序。
3. 插入排序。
排序原理:创建一个空数组,遍历排序数组的每个元素,使其插入到创建数组的合理位
置,完成排序。
例如:数组[3,7,2,9,3,1,0,6] 的排序过程:
[3] [7 2 9 3 1 0 6]
[3 7] [2 9 3 1 0 6]
[2 3 7] [9 3 1 0 6]
… …
[0 1 2 3 3 6 7 9]
插入的详细过程如下:
[1 5 8 9] [4]
首先让4和9比较,如果4<9,两者交换位置;4再和8比较,两者交换位置;4再和5比较,两者交换位置;4和1比较,4>1,跳出循环,插入过程结束。
程序如下:
void insertSort(int test[],int length){ int i,j,pos,num; for(i=1;i<length;i++){ //寻找插入的位置的同时,让数组元素右移 j=i-1; pos=i; //pos记录当前test[i]的位置 num=test[i]; //记录要插入的值 while(num<test[j] && j>=0){ test[pos]=test[j]; pos=j; j--; } test[pos]=num; }}
4. 希尔排序。
排序原理:希尔排序是基于插入排序的方法;通过增量delta将序列分成几个小序列,通过插入排序使小序列有序;当delta=1时,完成排序后即完成了最终排序。
例如:数组[3,7,2,9,3,1,0,6] 的排序过程:
当delta=4时,数组分为4组,如下所示:
每一组进行插入排序,得到结果:[3 1 0 6 3 7 2 9]
当delta=2时,数据分为2组,如下所示:
每一组进行插入排序,得到结果: [0 1 2 6 3 7 3 9]
当delta=1时,完成排序,结果为:[0 1 2 3 3 6 7 9]
程序如下:
#include <stdio.h>//输出数组void outputArray(int test[],int length){ int i; for(i=0;i<length;i++) { printf("%d ",test[i]); } printf("\n");}void insertSort(int test[],int length,int delta){ int i,j,k,pos,num; //有k个子序列 for(k=0;k<delta;k++){ for(i=k+delta;i<length;i+=delta){ j=i-delta; pos=i; num=test[i]; while(num<test[j] && j>=0){ test[pos]=test[j]; pos=j; j-=delta; } test[pos]=num; } } outputArray(test,length);}void shellSort(int test[],int length,int delta[],int delta_length){ for(int i=0;i<delta_length;i++){ insertSort(test,length,delta[i]); }}int main(){ int test[]={3,7,2,9,3,1,0,6}; //设置增量数组 int delta[]={4,2,1}; int length=sizeof(test)/sizeof(int); int delta_length=sizeof(delta)/sizeof(int); printf("排序前:"); outputArray(test,length); printf("排序后:"); shellSort(test,length,delta,delta_length); return 0;}
一般认为希尔排序的时间复杂度为O(n^1.5),适用于中规模序列排序。希尔排序是不稳定的排序。
5. 归并排序。
排序原理:运用了分治法的思想,把序列平均分成两段,把两段分别进行排序,再把排
好的两段合在一起。对于子段排序时,递归调用上面的过程。
例如:数组[3,7,2,9,3,1,0,6] 的排序过程:
[3 7 2 9] [3 1 0 6] 分组
[3 7] [2 9] [3 1] [0 6] 递归分组
[3 7] [2 9] [1 3] [0 6] 排序
[2 3 7 9] [0 1 3 6] 合并
[0 1 2 3 3 6 7 9] 再合并,得到排序结果
合并的原理:设置两个指向子序列开始位置的指针,再建立一个空数组。让两个指针指
向的值进行比较,较小的值进入数组,指向较小数的指针加1,指
向下个位置。重复以上步骤,直到所有元素进入数组。
程序如下:
#include <stdio.h>//输出数组void outputArray(int test[],int length){ int i; for(i=0;i<length;i++) { printf("%d ",test[i]); } printf("\n");}//将test数组的一部分进行归并排序void mergeSort(int test[],int beginIndex,int endIndex,int length){ //printf("调用函数mergeSort(test,%d,%d);\n",beginIndex,endIndex); int LL=endIndex-beginIndex+1; int mid=(beginIndex+endIndex)/2; if(LL==2){ if(test[beginIndex]>test[endIndex]){ int TT=test[beginIndex]; test[beginIndex]=test[endIndex]; test[endIndex]=TT; } } else if(LL>2){ mergeSort(test,beginIndex,mid,length); mergeSort(test,mid+1,endIndex,length); //合并的过程 int i=beginIndex; int j=mid+1; int k=0; int* temp=new int[LL]; while(i<=mid && j<=endIndex){ if(test[i]<=test[j]){ temp[k]=test[i]; k++;i++; } else{ temp[k]=test[j]; k++;j++; } } while(i<=mid){ temp[k]=test[i]; k++;i++; } while(j<=endIndex){ temp[k]=test[j]; k++;j++; } //将temp写回test int ii,jj; for(ii=beginIndex,jj=0;ii<=endIndex;ii++,jj++){ test[ii]=temp[jj]; } } //outputArray(test,length);}int main(){ int test[]={3,7,2,9,3,1,0,6}; int length=sizeof(test)/sizeof(int); printf("排序前:\n"); outputArray(test,length); printf("排序后:\n"); mergeSort(test,0,length-1,length); outputArray(test,length); return 0;}
6. 快速排序。
排序原理:选择一个初始元素a,利用算法将数组分为两段:比a小,比a大。将比a
小的元素放在a前面,比a大的元素放在a的后面。再使用递归对前后两段进行
如下操作,当每段元素只有2个或3个时,就停止上面操作,排序完成。
分组原理:假设序列为r[left],r[left+1],… … ,r[right],设置两个指针i和j,指向left和right。
x=r[left];反复执行以下操作使得i,j相遇。
①j向左扫描,直到r[j]<x,r[i]=r[j],r[j]置为空;
②i向右扫描,直到r[i]>x,r[j]=r[i],r[i]置为空。
例如:数组[3,7,2,9,3,1,0,6] 的分组排序过程:
[(3) 7 2 9 3 1 0 6]
[* 7 2 9 3 1 0 6]
[0 7 2 9 3 1 * 6]
[0 7 2 9 3 1 * 6]
[0 * 2 9 3 1 7 6]
[0 * 2 9 3 1 7 6]
[0 1 2 9 3 * 7 6]
[0 1 2 9 3 * 7 6]
[0 1 2 * 3 9 7 6]
[0 1 2 * 3 9 7 6]
[0 1 2] [3] [3 9 7 6](一趟排序完成)
#include <stdio.h>#define NAN -1//输出数组void outputArray(int test[],int length){ int i; //printf("%d ",sizeof(test)/sizeof(int)); for(i=0;i<length;i++) { printf("%d ",test[i]); } printf("\n");}//快速分组int quickClassify(int test[],int left,int right){ int i=left; int j=right; int x=test[left]; while(i<j) { while(test[j]>=x && i<j) j--; test[i]=test[j];test[j]=NAN; if(i>=j) break; i++; while(test[i]<=x && i<j) i++; test[j]=test[i];test[i]=NAN; if(i>=j) break; j--; } test[i]=x; //printf("last i=%d,j=%d\n",i,j); return i;}//快速排序void quickSort(int test[],int left,int right){ if(left<right){ int n=quickClassify(test,left,right); quickSort(test,left,n-1); quickSort(test,n+1,right); }}int main(){ int test[]={3,7,2,9,3,1,0,6}; int length=sizeof(test)/sizeof(int); printf("排序前:"); outputArray(test,length); printf("排序后:"); quickSort(test,0,length-1); outputArray(test,length); return 0;}
快速排序的最好情况是每趟将序列分成两半,正好在表中间,时间复杂度O(nlogn);快速排序最坏的情况是已经排好序,时间复杂度O(n^2)。快速排序是不稳定的排序。
7. 堆排序。
排序原理:首先介绍大根堆和小根堆:一颗二叉树,如果它的所有子节点都比它们的父节点小;通过构建大根堆和小根堆可以求出序列的最大值或最小值。
排序原理:将序列看成是一颗二叉树。构建大根堆,求出序列的最大值,与序列尾部元素交换位置;再求出剩下元素的最大值。重复以上步骤,直到得到一个从小到大的序列。
例如:数组[3,7,2,9,3,1,0,6] 的分组排序过程:
将序列看成是一棵二叉树,整个排序分为两个部分:新建堆,将最大元与最后元素转换后的重建堆。
程序如下:
#include <stdio.h>void sift(int test[],int k,int m)//假设test[k..m]是以r[k]为根的完全二叉树{ int temp=test[k]; int x=test[k]; //保存当前调整的值 int i=k; int j=2*i; int finished=0; while(j<=m && !finished){ if(j<m && test[j]<test[j+1]) j++; if(x>=test[j]) finished=1; else{ test[i]=test[j]; //向上移 i=j; j=2*i; } } test[i]=temp;}void create_heap(int test[],int length){ int i; for(i=length/2-1;i>=0;i--){ sift(test,i,length-1); }}void heapSort(int test[],int length){ int i; create_heap(test,length); for(i=length-1;i>=1;i--){ int temp=test[0]; test[0]=test[i]; test[i]=temp; sift(test,0,i-1); }}//输出数组void outputArray(int test[],int length){ int i; //printf("%d ",sizeof(test)/sizeof(int)); for(i=0;i<length;i++) { printf("%d ",test[i]); } printf("\n");}int main(){ int test[]={3,7,2,9,3,1,0,6}; int length=sizeof(test)/sizeof(int); printf("排序前:"); outputArray(test,length); printf("排序后:"); heapSort(test,length); outputArray(test,length); return 0;}
堆排序时间复杂度在最好和最坏的情况下都是 ;堆排序是不稳定的排序。
- 基础算法(排序)
- 基础排序算法(冒泡排序、选择排序、插入排序)
- 排序算法---基础算法(冒泡排序,快速排序,选择排序,直接插入排序,桶排序)
- 基础算法系列(五)排序算法之冒泡排序
- 基础算法系列(六)排序算法之鸡尾酒排序
- 基础算法系列(七)排序算法之插入排序
- 基础算法系列(八)排序算法之桶排序
- 基础算法系列(九)排序算法之计数排序
- 基础算法系列(十)排序算法之合并排序
- 基础算法系列(十三)排序算法之地精排序
- 基础算法系列(十四)排序算法之图书馆排序
- 基础算法系列(十五)排序算法之选择排序
- 基础算法系列(十六)排序算法之希尔排序
- 基础算法系列(十七)排序算法之堆排序
- 基础算法系列(十八)排序算法之快速排序
- 基础算法系列(十九)排序算法之内省排序
- 基础排序算法总结(七种排序算法)
- 【基础算法】排序-复杂排序之三(堆排序)
- Dubbo源代码实现一:切入Spring
- Flume快速入门(五):File Channel之重播(replay)
- 常用限流方案的设计和实现
- RocketMQ初探一:NameServer的作用
- Flume快速入门(一):背景简介
- 基础算法(排序)
- JNI综合实验一:LED点亮+IO电平读取
- Flume快速入门(二):设计从简
- Flume快速入门(三):File Channel之写Event
- JAVA基础---集合(五)--Set
- Flume快速入门(四):File Channel之FlumeEventQueue
- AbstractQueuedSynchronizer初探
- 小米网抢购系统开发实践
- 信号量Semaphore初探