汉诺塔问题, 用递归方法求集合中的中位数

打印解决汉诺塔问题的所有步骤

 1 void Move(int n, int start, int goal, int temp)
 2 {
 3     if (n >= 1)
 4     {
 5         Move(n - 1, start, temp, goal);        //将最上面的n-1个盘子移到temp柱子上
 6         printf("Move disk %d from %d to %d.\n", n, start, goal);    //将第n个柱子移到goal柱子上
 7         Move(n - 1, temp, goal, start);        //将temp柱子上的n - 1个柱子移到goal柱子上
 8     }
 9         
10     
11 }

 用递归方法求集合中的中位数

 1 void Swap(ElementType *X, ElementType *Y)
 2 {
 3     ElementType temp;
 4     temp = *X;
 5     *X = *Y;
 6     *Y = temp;
 7 }
 8 
 9 ElementType FindKthLargest(ElementType s[], int K, int Left, int Right)
10 {    //在s[Left]……s[Right]中找第K大的元素
11     ElementType e = s[Left];        //简单取首元素为基准
12     int L = Left, R = Right;
13     
14     while (1)
15     {
16         while ((Left <= Right) && (e <= s[Left])) Left++;    
17         while ((Left < Right) && (e > s[Right])) Right--;
18         if (Left < Right)
19             Swap(&s[Left], &s[Right]);
20         else
21             break;    //最终brak退出时,Left一定指向第二个集合的第一个元素
22     }
23     Swap(&s[Left - 1], &s[L]);
24     if ((Left - L - 1) >= K)
25         return FindKthLargest(s, K, L, Left - 2);    //Left - 1是基准,所以下一次递归的右边界应该是Left - 2
26     else
27     if ((Left - L - 1) < K - 1)
28         return FindKthLargest(s, K - (Left - L - 1) - 1, Left, R);    //K 先减去第一个集合的Left - L - 1个元素,在减去基准元素,所以下一次递归应该是在第二个集合中求第K - (Left - L - 1) - 1个元素
29     else
30         return e;        //找到,返回
31 }
32 
33 //封装前面这个查找函数
34 ElementType Median(ElementType s[], int N)
35 {
36     return FindKthLargest(s, (N + 1) / 2, 0, N - 1);
37 }

这个方法实际上利用了和快速排序相同的思路

简单选取S中的第一个元素e,根据e将集合S分为{e}和大于等于e的元素集合S1、小于e的元素集合S2; 然后通过判别集合S1的大小,将从S集合中找第K大数问题转换为在S1 和S2中的查找问题,由于S1或S2中的集合规模都比S小,这样就将复杂的问题转化为规模相对较小的问题,这也是递归函数的设计基础

上一篇:详述.NET里class和struct的异同


下一篇:树的引子, 顺序查找和二分查找