常用排序(二)
来源:互联网 发布:mac os x10.8下载地址 编辑:程序博客网 时间:2024/06/13 12:48
选择排序
选择排序说的是:每一趟在后面没有排序n-i个元素中,选择一个最小的放在第 i 个位置上,接下来选择i+1位置上的元素,一共需要执行n-2趟操作,他的时间复杂度是O(N*N)
选择排序有三种实现方式;直接选择排序、锦标赛排序、堆排序
1.直接选择排序
选择最小的元素,如果不是第一个就和第一个对调位置,这样他就是第一个了,重复直到排序结束
void SelectSort(dataList<int>& L,int left,int right){for(int i =left;i<right;i++){int k = i;//代表最小码for(int j = i+1;j<=right;j++){if(L[k]>L[j]) k=j;}if(k!=i) Swap(L[i],L[k]);//交换}}最坏情况下总的移动次数是3(N-1)次,总的比较次数是N(N-1)/2次
2.锦标赛排序
锦标赛排序的思想是:取N个元素的,两两进行比较,较小的保留下来,会得到N/2个元素,接下俩对着N/2个元素继续两两比较,直到选出最小的为止
胜者树是最底层的叶子节点是元素原本的样子,然后每两个叶节点进行比较,比较的结果变成他们的父节点,父节点之间在进行比较,最终根节点就是选择出来最小的结点,最底层的叶节点叫做胜者树的外部节点,非叶节点叫做内部节点
用胜者树对N个元素进行排序时,时间代价是O(nlog2 n)
void TournmentSort(int a[],int left,int right){size = right-left+1;WinnerTree<int> wt(size);int data[size+1];for(int i =1;i<=size;i++){a[i+left-1] = data[i];}wt.Initial(data,size,Winner);//初始化胜者树for(i=1;i<=size;i++){a[i+left-1] = wt.Winner();//wt.Update();//修改胜者wt.rePlay(t[1],Winner);//重构,选出新的胜者if(wt.Winner()==maxValue) break;}}3.堆排序
先是根据元素数据利用堆的调整算法siftDown实现初始堆,接下来元素交换调整进行排序
先来说说最小堆的调整,一般而言有两种调整策略,从上到下的下滑调整和从下到上的上滑调整
下滑调整是:从父节点出发,看他的左右两个儿子中有没有比他大的,如果有的话就小的上移
上滑调整:和下滑正好相反,他是从儿子出发,看看父节点是否比他小,如果父节点小的话就不调整,若父节点大的话就调整、
void siftDown(int start,int m){//从start开始到m为止int i= start;int j = 2*i+1;//父节点是I,左子女是2*i+1int temp = heap[i];while(j<=m){if(j<=m && heap[j]>heap[j+1]) j++;//找到左右子女最小的if(temp<=heap[j]) break;else{heap[i] = heap[j];// i 节点的值现在是小的,然后 j 的值现在还是原来的i=j;j=2*j+1;}//原来的J结点变成父节点,继续找最小值,下移了一层}heap[i] = temp;//把最开始的I值放在最后的父节点上 }void siftUp(int start){//从start向上到节点0int j=start,i = (j-1)/2,temp = heap[j];while(j>0){if(heap[i]<=temp) break;else{heap[j] = heap[i];j = i;i = (i-1)/2;}}heap[j] = temp;}
在到堆排序中用的是最大堆,上面的代码是最小堆,当把最大的也就是堆顶的元素得到之后放在最后一个n-1的位置上,再找下一个元素
void HeapSort(maxHeap<int>& H){//对H.heap[0]到H.heap[currentSize-1]排序for(int i = (currentSize-2)/2;i>=0;i--){//表转化为堆siftDown(i,currentSize-1);}for(i = currentSize-1;i>=0;i--){//表排序Swap(0,i);siftDown(0,i-1);//交换重建最大堆}}
主要解释一下第一个for循环,i=curr-2/2,这指的是最后两个元素所对应的父节点的位置,因为 j = 2*i+1是左节点,j = 2*i+2是右节点,这里先从最右边父节点就开始建立堆,从(curr-2)/2开始到curr-1,建立堆,只有一个父节点,然后开始i--,建立下一个父节点,直到所有的节点都被建立完全,然后第二个for循环是找到最大的数然后放在后面,当前最大的数是堆顶元素,是heap(0)的元素,把他和curr-1交换,这样他就在最后一个,接下来重新建立前面n-2和元素的最大堆,取出堆顶元素在放在curr-2的位置上,这样一次循环下去直到所有的都排好序
归并排序
归并排序也采用的是分治法,将大的序列分解为两个小的序列,序列长度相等,然后再将两个合并起来,其中的难点是合并
void merge(dataList<int>& L1,dataList<int>& L2,int left,int mid,int right){int s1 = left,s2 = right,t = left,k;//s1和s2是检测指针,t是存放指针for(k = left;k<=mid;k++){L2[k] = L1[k];//将L1的正向全部复制到L2}for(k = mid+1;k<=right;k++){L2[right-(k-mid-1)] = L1[k];//反向复制}while(t<=right){//归并if(L2[s1]<=L2[s2]) L1[t++] = L2[s1++];<span style="white-space:pre"></span>//S1的数值小取出来放在L[t]中else L1[t++] = L2[s2--];<span style="white-space:pre"></span>//s2小取出来放入T中}}
基数排序
每个元素的排序码有多个,排序时要用多排序码排序,利用多排序码排序实现对单个排序码的排序叫做基数排序,多排序码排序包含有最高位优先MSD和最低位优先LSD两种。
在MSD中,把单排序码看作是一个子排序码组,由好几个组成,例如三位数可以看成是有百位、十位、个位三个排序码组在一起形成的,这样排序时可以按照一个一个的排序码进行排序,比如先排百位再排十位个位
void RadixSort(dataList<int>& L,int left,int right,int d){//d表达的是第几位数,d=1是最低位int radix = 10;int i,j,count[radix],p1,p2;//count[k]处理第 i 位时,第 i 位值等于k的个数Element<int> array[right-left+1];//存放按桶分配结果if(d<=0) return;if(right-left+1<=M) InsertSort(L,left,right);//小的序列插排for(j=0;j<radix;j++) count[j]=0;//初始化for(i=left;i<=right;i++) //统计各桶元素count[getDigit(L[i],d)]++;for(j=1;j<radix;j++) //各桶元素存放位置count[j]=count[j]+count[j-1];for(i=left;i<=right;i++){//分配桶中j = getDigit(L[i],d);//取L[i]的第 d 位值array[count[j]-1] = L[i];count[j]--;}for(i=left,j=0;i<=right;i++,j++) L[i]=array[j];//写入原数组for(j=0;j<radix;j++){递归对d-1位处理p1 = count[j];//开始端p2 = count[j+1]-1;//尾端RadixSort(L,p1,p2,d-1);}}
另外附上一个学习网站,当你不了解他是如何工作的时候,可以看看他的动画演示https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
- 常用排序(二)
- 常用排序(二)
- 常用排序方法(二)
- C语言常用排序算法(二)
- 常用的排序方法(二)
- 常用排序算法、二
- 常用排序算法总结(二)
- 常用排序算法总结(二)
- 常用排序算法总结(二)
- Java常用排序算法(二):选择排序
- 【算法之常用排序算法(二)】常用排序算法性能比较,及常见面试题
- 【Java常用排序算法】归并排序(二路归并排序)
- 常用算法总结之排序(二)----基本冒泡
- 学习Linux笔记(二)-常用+查找排序
- 几种常用的高效排序(二)--堆排
- 常用代码段(二)冒泡排序算法Java实现
- 几种常用的排序算法(二)--python实现
- 常用排序算法总结(二) ---- 插入排序,快速排序
- PMD规则之String and StringBuffer Rules
- ExtJS开发,实现轮播图
- Mybatis入门概述及第一个Mybatis实例实现增删改查
- mysql(八):mysql常用函数
- 根据某个View获得图片
- 常用排序(二)
- JAVA-1 简介
- poj 1061 青蛙的约会(数论)
- maven-->update project
- srs 如何集成rannet
- Mybatis中mapper.xml中的模糊查询
- 数据库索引
- 直接插入排序
- win系统下nodejs安装及环境配置