2015年8月21日星期五

快速排序的简单实现 - lijihong0723

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
快速排序的简单实现 - lijihong0723  阅读原文»

  算法这一块是我的弱项。就以快速排序这样简单的算法,大二学完以后,就没有回顾过了。因为C中有qsort()接口,而C++中也有sort()接口。前一阵子想巩固一下基础知识,回顾了这一著名算法。

  因为大学学过,所以大致知道它的一个过程——也就是一个递归。设给定一序列arr[0...N],首先通过arr[0]将arr[0...N]一分为二(我比较懒,不画图了,大家将就看哈),如下:

  __前半部分,特点:这半部分序列中元素<arr[0]__ arr[0] __后半部分,特点:这半部分序列元素>= arr[0]_ (1)

                               ↑

                     pilot所在位置(是不是叫pilot的?我忘了,^_^)

  接下来,就是递归排序前半部分和后半部分,递归终止条件就是待排序的序列长度<=1。这个过程是不是很简单?那怎么找arr[0]所在位置,换句话说,怎么把原来的序列一分为二,满足(1)给定的条件?其实,这个问题我一开始也想了好久,第一版代码写出来运行结果还是不对的,经过调试才最后运行正确。

  这里必然要对序列进行遍历,并且遍历过程中要保持一定的要求——就是所谓的循环不变式(《算法导论》一开始就介绍这个概念了)。我们这里要满足的要求(或学术化一点叫循环不变式)可以这么描述:遍历过程中,假设现在循环变量值为i,我们要保证:

          arr'[0]...arr'[pilot-1] < arr'[pilot] <= arr'[pilot+1]...arr'      (2)

我们这里符号用的是arr'(上撇号),这里arr'[pilot]存放的是arr[0],采用不同符号以表示与原始序列不同了。

问题:怎么在遍历过程中,保持(2)成立???

  其实,想到也不难,可能要花点心思。首先把arr[0]保存下来,放在变量pilot_value中,初始的情形如下:

        ____ arr[1] arr[2]...arr[N]

         ↑   ↑

        pilot  i

因为arr[0]保存下来了,所以pilot所指的位置可以认为是没有意义了,所以我在画了一条线——表示这可以看做是空的。遍历从i=1开始,遍历的目的是把所有小于pilot_value的值放到pilot所指位置的左边(如上:初始的时候,pilot左边是没有元素)。现在我们假设循环变量到i+1了,表明前面i个元素满足(2)式要求了,现在就是移动arr到合适位置,如下:

        arr'[0]...arr'[pilot-1] < ___ <= arr'[pilot+1]...arr' arr                (3)

                     

                    pilot

很简单,就是比较pilot_value和arr,两种情况咯:

     (1)若 pilot_value <= arr,不需要做任何操作;

     (2)若pilot_value > arr,此时:直接将pilot位置上放置arr吗?那就试试看,如果这么做,就会出现如下情况:

              arr'[0]...arr'[pilot-1] arr arr'[pilot+1]...arr' _____              (4)

                                        ↑

                                      新的pilot

这时,pilot应该+1,即箭头指向的位置。我们知道pilot指向的位置在遍历完成后,是要存放arr[0](即:pilot_value)的,而此时pilot指向的是一个有意义的位置。注意(4)中最后一个位置存放的是arr,这个位置现在存放这个值还有意义吗?显然没意义了!这时只要把arr’[pilot+1]和下划线所在位置的值换一下就好了,这样新的pilot所指向的位置就可以认为没意义了——可以看做是空的了。最后结果如下:

            arr'[0]...arr'[pilot-1] arr _____ arr'[pilot+2]...arr'arr'[pilot+1]        (5)

                           ↑

                         新的pilot

其实现在 新的pilot所指向的位置存放的值时arr。(5)式显然是保持(2)式要求的。遍历完整个序列,得到最后的pilot,然后把pilot_value放到这个位置上,就可以了。最后查找pilot并整理序列以满足(2)式要求的函数实现如下(采用模板):

1 template <typename Type>
2 int find_pilot(Type arr[], int iLen) {
3 int my_pilot = 0;
4 int pilot_value = arr[0];
5
6 for (int i = 1; i != iLen; ++i) {
7 if (pilot_value > arr) {
8 // pilot位置上放上arr
9 arr[my_pilot] = arr;
10
11 // pilot自增
12 my_pilot++;
13
14 // pilot和arr交换,以保证pilot指向的值无意义。
15 std::swap(arr, arr[my_pilot]);
16 }
17 }
18
19 arr[my_pilot] = pilot_value;
20 return my_pilot;
21 }

  快速排序就是先通过上述函数将原始序列按pilot分为两个子序列,然后针对两个子序列分别递归调用,代码如下:

1 template <typename Type>
2 void quick_sort(Type arr[], int iLen) {
3 if (iLen <= 1) {
4 return;
5 }
6
7 int pilot = find_pilot(arr, iLen);
8 quick_sort(arr, pilot);
9 quick_sort(arr + pilot + 1, iLen - pilot - 1);
10 }

  最后,我们测试代码如下:

1 int main() {
2 std::cout << "= = = = = 快速排序算法 = = = = =" << std::endl;
3 std::cout << "排序前的数组:";
4
5 int iTestArray[10] = { 0 };
6 srand((unsigned int)time(NULL));
7 for (int i = 0; i != 10; ++i) {
8 iTestArray = rand() % 100;
9
MrHuo.OAuthLoginLibs社会化登录组件Github - MrHuo工作室  阅读原文»

今日写的博客

[原创]旧事重提:只配置参数实现OAuth2登录

引来很多园子里的朋友问候,所以今日花了一些时间整理了代码。

现已发布至github:

MrHuo.OAuthLoginLibs:https://github.com/mrhuo/MrHuo.OAuthLoginLibs

MrHuo.OAuthLogin.QQApis:https://github.com/mrhuo/MrHuo.OAuthLogin.QQApis

MrHuo.OAuthLoginLibs项目内的OAuthLoginDLLs是编译好的最新dll。

欢迎朋友们共同努力让这个组件走得更远。

先说下代码结构:

一、引用:

代码中使用了RestSharp作为网络访问。

关于RestSharp的介绍可以看(善友兄的)这篇文章:http://www.cnblogs.com/shanyou/archive/2012/01/27/RestSharp.html

代码中使用了DynamicJson作为Json解析。为什么选择此组件,因为他可以序列化对象为dynamic,而不用新建对象。

-------------------------------不美的分割线-----------------------------------------

二、代码图:

可以看出核心就是interfaces和core。此版本中包含中文简体、中文繁体、英文的资源文件。


-------------------------------不美的分割线-----------------------------------------

再看看core程序集的代码图:

1、AuthStateManager维护了一个内部的状态机,为了验证每次OAuth验证时带给第三方平台的状态。

2、AuthConfigManager管理已配置的配置文件。

3、OAuthToken是一个通用的Token基类,可根据不同平台继续扩展,目前已基本无需改动。

4、OAuthLoginResult是OAuth验证结果类。

5、OAuthContextBase<TOAuthToken, TUserInfo>是获取用户信息的上下文,是个抽象类。

具体实现参照这个项目MrHuo.OAuthLogin.QQApis

6、核心类就是OAuthLogin,只需要运用这一个类就可以执行OAuth登录了。

我在对象浏览器里截了张图:


-------------------------------不美的分割线-----------------------------------------

三、使用代码可以参考文头的文章。

看看使用效果:

1、QQ登录:

2、Sina效果:

3、Baidu效果:

其他登录因笔者没有申请到合适的key,所以无法得知结果如何。还请各位园子里的园友验证后告诉我。

四、其实OAuth登录到此还未完毕,接下来做的事就是,把获取到的用户的openid保存到数据库,创建一个网站内部用户和openid绑定。

接下来的工作就靠大家了。希望大家能喜欢这个组件。 just fork it.

联系方式:http://www.mrhuo.com

qq:491217650


本文链接:MrHuo.OAuthLoginLibs社会化登录组件Github,转载请注明。

阅读更多内容

没有评论:

发表评论