排序函数总结(待续)

来源:互联网 发布:富德生命网络商学院app 编辑:程序博客网 时间:2024/06/05 10:49

最近遇到了排序,每次都是用快排,冒泡,很少用别的,这里总结下,加深下自己的印象

这种文章已经多到如XXX,所以大家就择优阅读,我会慢慢补充,后面加上复杂度分析以及一些实际案例!希望本帖我会继续做下去

前几天看到有人说,如何让你的代码变得更加吸引人,其中一个方法就是运用模板,以前不怎么用,这里我就把排序全部用模板实现

其实这不是什么难度上的考察,而是一个人编程习惯的考察,以后要多多注意

//时间紧迫,就先简单贴上插入排序和希尔排序,因为二者还是紧密联系,要理解希尔,首先要理解清楚插入排序的规则

1、插入排序

就是逐步扩大有序区,这里有序区我假定在数组前部分,所以我们遍历的时候就是从第一个元素开始,在这之前没有元素,所以a[0]有序 现在判断a[1],我们发现a[1]<a[0],然后用一个index专门向有序区遍历,直至找到改元素位置。

[4] 2 5 1

[4 2] 5 1  --->[2 4] 5 1

[2 4 5] 1 ----> [2 4 5] 1

[2 4 5 1] --->  [2 4 1 5] --->  [2 1 4 5 ] --->[1 2 4 5]

就是这么一个过程啦(代码见InsertSotr())


2、希尔排序

它的思想是希望能够减少移动次数,例如上题的1 ,我们发现移动次数太多了,如果能够先判断到远的元素,那么是不是有更好的呢?这里存在一个间隔因子

interval 至少要有等于1的时候,全部排序一次,具体解释后面再补充,大家可以问问谷歌度娘


//============================================================================// Name        : SortMethods.cpp// Author      : YLF// Version     :// Copyright   : Your copyright notice// Description : Hello World in C++, Ansi-style//============================================================================#include <iostream>#include <time.h>using namespace std;#define MAX 100template<typename T>void printSortedArr(T* arr, int num);template<typename T>void InsertSort(T* arr, int num);template<typename T>void ShellSort(T *arr, int num);typedef double type;int main() {type input = 0;type arr[MAX];int num = -1;while(true){num++;cin>>input;if(input!=-1)arr[num] = input;elsebreak;}//InsertSort(arr, num);ShellSort(arr, num);return 0;}//插入排序/** * 前面的序列作为有序序列 */template<typename T>void InsertSort(T* arr, int num){int i = 0, j = 0;for(i=0; i<num;i++){j = i-1;while(j>=0){if(arr[j]>arr[j+1]){T temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}j--;}}printSortedArr(arr, num);}/** * 希尔排序 */template<typename T>void ShellSort(T *arr, int num){int interval = 3;int i = 0, j = 0;for(;interval>0;interval--){//分块for(i=0;i<(num+1)/interval;i++){//间隔interval分为同一块,所以遍历次数就是块数for(j=0;j<num;j=j+interval){int k = j - interval;while(k>=0){if(arr[k]>arr[k+interval]){T temp = arr[k];arr[k] = arr[k+interval];arr[k+interval] = temp;}k -= interval;}}}}printSortedArr(arr, num);}/* * 打印数组函数 */template<typename T>void printSortedArr(T* arr, int num){int i=0;for(i=0;i<num;i++)cout<<arr[i]<<",";cout<<endl;}

3、选择排序

//2013.10.13 今天继续补充几个 ,先简单的开始把

选择排序和冒泡排序个人感觉还是蛮相似的,走一圈找个最大最小的换到有序区,然后再遍历,

虽然平均的时间复杂度都是O(N^2)

不过冒泡的最好情况可以达到O(N)(一次都没有交换表示顺序已经排好,所以遍历一次即可)

选择排序则还是O(n^2),而且选择排序是不稳定的,冒泡是稳定的,

不过正如在http://blog.csdn.net/ylf13/article/details/12620185

我在这道题解法上来看,选择排序也是一个挺好理解的算法,废话不多说了,这个看代码足够了


/** * 选择排序 * 我这里每次循环都把最小的放到前面的有序区里 */template<typename T>void SelectSort(T* arr, int num){int i = 0;int minIndex = 0;//记录最小值的Indexint sortedIndex = 0;//有序区与无序区边界for(sortedIndex=0; sortedIndex<num-1;sortedIndex++){minIndex = sortedIndex;for(i=sortedIndex;i<num;i++){if(arr[i] < arr[minIndex])minIndex = i;}T temp = arr[sortedIndex];arr[sortedIndex] = arr[minIndex];arr[minIndex] = temp;}printSortedArr(arr,num);}

4、冒泡排序

这个大家再熟悉不过了把。。就是每次比较,如果前面的更大,就前后交换,不断把最大的冒泡到顶上,这个思想很重要,这里冒泡是相邻相邻的比,大家想想

是否存在冗余或者没必要的比较,个人感觉(纯属个人的想法,可能有问题,大家仔细斟酌)堆排序也是一种冒泡,只不过它冒泡的时候精简了比较次数,使得算法

从O(N^2)  ---> O(NlogN)  对于堆排序,下一个算法我就写,这个算法还是很值得大家考虑的,我觉得它的思想很好,可以派生出很多类似的算法,我也多多上网查查,

尽量写得完整点,好了,言归症状,不就一冒泡么。。。思想很重要

/** * 冒泡排序 * 这里把最大的往上冒  Oooooooo */template<class T>void BubbleSort(T* arr, int num){int i=0, j=0;for(i=num-1;i>0;i--){bool success = true;for(j=0;j<i;j++){if(arr[j] > arr[j+1]){T temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;success = false;}}//这一步是用来判断是否已经调整好了,如果提前就排序好就退出,不用继续了if(success)break;}printSortedArr(arr, num);}


5、堆排序

这里对堆排序大家可以理解成是一种跨越式的冒泡。

先说下堆

推荐参考:http://blog.csdn.net/morewindows/article/details/6709644

堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。

二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。

二叉堆满足二个特性:

1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆


堆其实是一种逻辑结构,而实际表示结构是数组


下面都以最大堆为例子

如图,上半部分就是一个逻辑结构,而我们实际表示是下图数组

堆的寻找过程就是先从20(15,5)这个分支找到最大值,然后在找出30(20,10)这个堆的最大值,这样我们就把最大值冒泡上来了,而以前我们是通过5和15比较,15在和10比较,然后和20比较,。。。这样存在很多多余比较次数,而堆排序这种逻辑结构很好的克服了,所以时间复杂度就成为o(N*logN)

http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html这篇文章也很推荐,他是把这种比较形式和选择排序进行比较

/* * 堆排序 */template <typename T>void HeapSort(T* arr, int num){//初始化堆成为最大堆int i=0;int sortedIndex = num;for(;sortedIndex>0;sortedIndex--){for(i=sortedIndex/2-1;i>=0;i--){maxHeap(arr, i, sortedIndex);}T temp = arr[0];arr[0] = arr[sortedIndex-1];arr[sortedIndex-1] = temp;}printSortedArr(arr,num);}template<typename T>void maxHeap(T* a, int index, int num){int i = index;int j = 2*i + 1;T temp = a[i];while(j<num){if(j+1 < num)if(a[j]<a[j+1])j++;if(a[j]>temp)a[i]= a[j];elsebreak;i = j;j = 2*i +1;}a[i] = temp;}

其实,如果换个角度,我们直接从数组来看


画的丑了点,大概就是这种过程



6、快速排序

【2013.10.17】

俗话说得好,贵在坚持 !!真TM难坚持。。。

今天碰巧写到快排了,赶紧过来补充下。。。

快排:时间复杂度

时间复杂度:O(n*lgn)
最坏:O(n^2)
空间复杂度:O(n*lgn)
不稳定。

快排原理如下:

首先找出个主元,就是作为中间比较元素

5 2 7 4 9 8

假设我们取a[0]=5作为主元,那么接下来就是和他比较,设两个指针i  j一个指向头,另一个指向尾,

5    2    7    4    9    8            (主元)temp=5

i                               j

首先移动J  if(arr[j]  < temp) 由于我们的规则是,把比主元5小的放在数组前面,比主元5大的放在数组后面,那么 如果arr[j]  小于 temp,那么arr[i] = arr[j],这时候i++

否则就是j--,过程如下

5    2    7    4    9    8            (主元)temp=5

 i                        j

5    2    7    4    9    8            (主元)temp=5

i                   j

好了,这时候4<5(主元)所以:

4    2    7    4    9    8            (主元)temp=5

i                    j

然后i++  注意绿色的4就是一个无效元素,等待被人取代

4    2    7    4    9    8            (主元)temp=5

       i            j

4    2    7    4    9    8            (主元)temp=5

       i            j

2还是小于5

4    2    7    4    9    8            (主元)temp=5

             i      j

这里7>5 所以

4    2    7    7    9    8            (主元)temp=5

             i      j

然后j--

4    2    7    7    9    8            (主元)temp=5

             ij

判断i==j??   a[i] = temp

4    2    5    7    9    8            (主元)temp=5

             ij

好啦,然后采用分而治之的方法即可。。。

void QuickSort(int* &arr, int l, int h){int i = l;int j = h;int temp = arr[i];while(i < j){while(i<j && arr[j]>temp)j--;if(i<j){arr[i] = arr[j];i++;}while(i<j && arr[i]<temp)i++;if(i<j){arr[j] = arr[i];j--;}}arr[i] = temp;if(i-1>l)QuickSort(arr,l,i-1);if(i+1<h)QuickSort(arr,i+1,h);}

很多算法题目,给的是一些乱序的数组,要我们找出某个规律的东西,如果能排序下就会发现很多答案就呈现出来,一般排序后的算法复杂度都降为O(N)

例如:字母排序 http://blog.csdn.net/ylf13/article/details/12835037

            数字排序http://blog.csdn.net/ylf13/article/details/12776639







原创粉丝点击