f(sixleaves) = sixleaves

重剑无锋 大巧不工

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  95 随笔 :: 0 文章 :: 7 评论 :: 0 Trackbacks

#

总结下cocos2dx的这些动作,知识大概的总结,不是包含所有。文中的名词是自己取得。
首先我们要把握主线,我们在cocos2dx用到的动作都是派生自Action类,而Action又派生自Ref类。而我们主要用到的时属于Action派生的FiniteTimeAction(有限时间的动作类)类所派生的类。
FiniteTimeAction中得有限时间类又分为两个部分,一个部分是瞬时动作类(ActionInstant),也就是执行时你是看不到过程,只能看到结果。一部分是ActionInterval(持续动作类),这类动作都是有持续时间的。
1.框架:
Action类派生出:FiniteTimeAction
#FiniteTimeAction类派生出:ActionInstant类和ActionInterval类
##ActionInstant类派生出:CallFunc类、FlipX、Hide、Place(这里只是列出我常用的)
##ActionInterval类派生出:又分为两大类,一大类是纯持续动作类、一大类是动作包装类(这是我自己细分的)
其中纯持续动作类包括:BezierBy(To)(贝兹尔曲线动作)、Blink(闪烁动作)、FadeIn(Out)、JumpBy(To)(跳转动作,指定起跳位置、高度、次数)、RotateBy(To)、ScaleBy(To)(拉伸动作)。
其中一般By是相对的意思当前位置或者倍数,To是指定绝对。第一个参数都是指定持续时间。
其中动作包装类包括::Repeat、RepeatForever、Sequence、Spawn,动作包装类对所包装的动作有一定副作用,其副作用一般可顾名思义。
如上,Repeat包装后的动作就是重复指定次数被包装的动作、RepeatForever则是持续不断、Sequence可以包装多个动作、其副作用是让多个动作顺序执行
Spawn包装后的动作的副作用是,所有动作一起执行。

2.动作的创建:
一般动作的创建是调用相应动作的类的create工厂方法。

3.动作的执行:
一般动作的是发送runAction消息给指定的Sprite对象,传入参数就是动作对象。

4.几个重要动作Sequence、Spawn、CallFunc
Sequence动作的使用就是如代码:
auto actions = Sequence::create(action1,action2,...,actionN, NULL);
sprite->runAction(actions);
Spawn的使用也一样,知识把关键字替换掉
CallFunc动作是我们就称为回调动作把(或者说是把函数转化为动作),传入的第二个函数指针需要通过callFunc_selector格式化该函数指针。
auto actionCF= CallFunc::create(this, callFunc_selector(HelloWord::sayLove));

posted @ 2014-09-28 16:13 swp 阅读(1228) | 评论 (0)编辑 收藏

在写程序中,我们经常要判断,或者写个循环,具体让其循环几次,这个怎么计算。
我分别举几个例子。
eg1:for (i = 0; i < n; i++);
这个是大家再熟悉不过的了,为什么它是n次循环,如果我能用数学的角度看是这样的,首先i的取值范围中,每个整数对应一个
循环,所以所谓的循环次数,也就是这个范围内的整数的个数。而上述的循环范围是[0, n).它的整数个数就是n - 0 = n,只有
对于半闭合半开放的区间能这样计算,这也是为什么从0开始计数的好处之一。一目了然。
eg2:
while(L--) {
}
这个循环循环几次呢,首先我们确定L的有效范围,由于是后置减减,所以有效范围是[L, 0).所以循环也是L次
如果是
while(--L){},那范围就是[L-1, 0),所以其循环次数是L - 1
posted @ 2014-09-23 21:02 swp 阅读(1083) | 评论 (0)编辑 收藏

题目描述

为了缩短领救济品的队伍,NNGLRP决定了以下策略:每天所有来申请救济品的人会被放在一个大圆圈,面朝里面。选定一个人为编号 1 号,其他的就从那个人开始逆时针开始编号直到 N。一个官员一开始逆时针数,数 k 个申请者,然后另一个官员第 N 个始顺时针方向数 m 个申请者,这两个人就被送去再教育。如果两个官员数的是同一个人,那个人则被送去从政,然后2个官员再在剩下的人里面继续选直到没人剩下来,注意两个被选 中的人是同时走掉的,所以就有可能两个官员选中一个人。

[编辑]Input

输入含有多组测试资料,每组测试资料一列含有三个数 N,k 和 m(k, m > 0,0<N<20)。 当输入为 0 0 0 代表输入结束。

[编辑]Output

对每组测试资料输出一列。输出被选中的申请者的编号顺序(一对一对的)。每个数的宽度为 3 。每一对前面的那个编号为逆时针数的官员选出的,后面的那个编号为顺时针数的官员选出的(但是如果这2个官员选出同一个人,那就只会有一个编号)。每一对 之间以逗号分开。格式请参考Sample Output。

[编辑]Sample Input

10 4 3 
13 17 42
7 8 47
0 0 0

[编辑]Sample Output

 4 8, 9 5, 3 1, 2 6, 10, 7 
4 11, 10 1, 8 6, 13 7, 3, 5 12, 9 2
1 3, 5 7, 2 4, 6
这道题目有点绕,也讲得不严密。这里主要说下几个容易错的地方。
首先是你每次在写程序之前,都要十分清除规则,题目中的人是围着一圈,而且第一个的左边是第N个人,也就是它是逆时针标号的。这个十分关键。
其次是go函数的实现,go函数是数过L个人,返回最后一个的位置。我并不赞同,某些版本数组是从1开始计数,因为这样对于表达式的表达十分不方便。你可以
自己尝试用1来做,会很不方便。就是因为go函数是这样一个函数,所以当我们在下一次迭代的时候的开始位置,一定是为那个人出去的位置,也就是a[i]=0的位置。
所以我们第一次迭代的位置,原本A是应该在位置0,B在位置n-1。这时候只能是A在n-1和B在0.(你可以用数学归纳法理解)。
 1 #include <stdio.h>
 2 
 3 #define MAXN 25
 4 int n,k,m;
 5 int a[MAXN];
 6 int go(int p, int d, int k);//数过k个人,开始位置p必须是数1时候的前一个位置。 
 7 int main() {
 8     while (scanf("%d%d%d", &n, &k, &m) == 3 && n) {
 9         for (int i = 0; i < n; i++) {
10             a[i] = i + 1;
11         }
12         int left = n;
13         int pA = n-1, pB = 0;
14         int pANext,pBNext;
15         while (left) {
16             pA = go(pA, 1, k);//1表示逆时针,因为它是逆时针标号
17             pB = go(pB, -1, m);//-1表示顺时针
18             printf("%3d", pA + 1); left--;
19             if (pA != pB) { printf("%3d", pB + 1); left--;}
20             a[pA] = a[pB] = 0;
21             if (left) printf(",");
22         }
23         printf("\n");
24     }    
25     return 0;
26 }
27 int go(int p, int d, int L) {
28     while (L--) {
29         do { p = (p+n+d)%n;} while(a[p] == 0);
30     }
31     return p;
32 }
解析:至于下一个位置为什么是p = (p+n+d)%n.其实很简单。因为我们是一步步走的,所以只有两种边界情况。假设当前位置是p(0=<p<n),
第一种边界:p + 1 > n - 1,即 p + 1此时应该是到达0位置,但此时p + 1 = n,如果我们取余数,则 (p+1)%T = 0,T = n(T表示这个圆圈的周期大小)。
刚好能符合,又因为T = n,所以(P+T+1)%T还是不变的。
第二种边界: p - 1 < 0, 即 p - 1此时的值是-1,对于这种情况可以反过来看,它是向后退后1个单位,可以看成向前走T - 1个单位即p -1 等效于 p + T - 1
,我们要等到此时的位置,再去余,(P+T-1)%T。
对于情况一、二。可以归纳为(P+T+d)%T,当为顺时针是d取1,否则-1.
posted @ 2014-09-23 20:46 swp 阅读(1815) | 评论 (0)编辑 收藏

1.创建对象:

     在java中创建对象只能用new才行,返回的是引用类型,所以对象名其实是引用。而C++中的对象创建不一样,C++可以用指针存对象,相当于引用。也可以直接用类标识符来创建对象。如Person是类,Person a,b;在C++中就创建了两个对象,在java中是Person对象的引用。

2.C++中了this指针:

     C++中的this指针和java中的一样。在C++中,this指针指向当前对象,this指针隐含在每个成员函数之中,其类型是class className *.

     内部机制:

     在C++中访问数据成员都是隐含的使用this指针操作的。需要注意的是。

     1.this指针是const类型,不可改变。

     2.this指针针对对象,所以静态成员是没有this指针的。

3.构造函数和析构函数

     构造函数就不说了,只说下默认构造函数就死className() {},默认会生成。但是如果你自己定义了构造函数,而且不是定义成默认构造函数,就要在定义一下默认构造函数,不然创建对象时候必须指定参数,不能用无参数的。

     析构函数,就是用来在对象要销毁时候,回收一些对象自己向系统申请的内存。析构函数调用完后,系统才清除对象本身占据的内存。

      Tips:

       1.析构函数不能重载,只有一种形式~className() {},这是和构造函数的区别

       2.三种情况下调用析构函数,对象离开局部作用域后,撤销对象触发,程序终止,触发;delete运算符回收new创建的对象触发;临时匿名函数使用完毕;

4.拷贝构造函数和单参构造函数

        (1)拷贝构造函数,其实就是构造函数中的单参数形式的构造函数,只是其参数比较特别,是对自身同类对象的引用。拷贝构造函数在一下几个的方会用到。

         Date a;Date b(a);//调用的就是拷贝构造函数

         Date b = a;//调用的也是拷贝构造函数

         function(Date d){….};function(a);//调用的也是拷贝构造函数(先创建Date类的匿名对象,然后调用拷贝构造函数)

         Date c = function(a);//这边function返回Date对象,也是调用拷贝构造函数(没有创建匿名对象)

         (2)单参构造函数

          单参数构造函数。其实拷贝构造函数也是单参构造函数。但是我将他们区别开来,主要是单参构造函数,主要是用在,隐式的类型转换上。

          如你定义了一个Integer类,直接Integer a = 1;是会出错的。因为1不能自动或者隐含的转换成Integer对象,所以这时候你就要定义

          单参数构造函数,用来让自动转换,在java中称为包装。由于是构造函数,参数中的类型就是那个要转换的类型。其它和基本构造函数一样。

5.静态成员

        静态成员又分为静态数据成员和静态函数成员。C++中的静态函数成员和java也没区别。主要是静态数据成员。所以我们总结下静态数据成员

      (1)静态数据成员和类共存亡而不是和对象。

      (2)静态数据成员在类加载时候分配空间并进行初始化,而不是在对象加载时候。所以静态数据成员默认初始化为0。

             重点是:类中的静态数据成员知识一份声明,必须在类外重新定义并初始化静态数据成员。

      (3)类外通过类作用域运算符::访问静态数据成员。

6.const用法

        (1)const成员函数,这时候const加载函数名后面 {}之前。表示函数不会改变当前对象的状态,而且只能调用const成员函数。(养成习惯,能加尽量加)

               Tips:这里const也是函数签名的一部分。

        (2)const对象,表示常量对象。

        (3)const形参,表示函数中不会改变该形参。注意:常量对象,只能调用const成员函数,因为这才能保证状态不被改变,同时这样保证了他就是常量对象。

                Tips:这里const也是函数签名的一部分。

         (4)const返回值,说明返回值是不可以改变的。

以上这些都是总结,不是写给没基础的人看的。只是为了方便整理和记忆。

posted @ 2014-09-04 17:18 swp 阅读(295) | 评论 (0)编辑 收藏

这道题目是大数加法。总结一些一点经验。

(1)整值函数的应用。(这个不懂的话,去看我Math栏目下有这个分析)

(2)sscanf、sprintf的应用

(3)分块计算的格式问题。

先直接看代码:
    
 1 #include <iostream>

 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 using namespace std;
 6 struct BigInteger {
 7     static const int BASE = 100000000;
 8     static const int WIDTH = 8;
 9     vector<int> s;
10     
11     BigInteger(long long num = 0) {
12         *this = num;
13     }
14     
15     BigInteger operator=(long long num) {
16         s.clear();
17         do {
18             s.push_back(num % BASE);
19             num /= BASE;
20         }while (num > 0);
21         return *this;
22     }
23     
24 
25     BigInteger operator=(const string& str) {
26         s.clear();
27         int x;
28         int len = (str.size() - 1) / WIDTH + 1;//这里有人看不懂,请看我写的整值函数 
29         for (int i = 0; i < len; i++) {
30             int end = str.size() - i * WIDTH;
31             int start = max(0, end - WIDTH);//确定分割的区间为[start, end)是左闭右开,长度就是end - start 
32             sscanf(str.substr(start, end - start).c_str(), "%d", &x);
33             s.push_back(x);
34         }
35         return *this;
36     }
37     
38     BigInteger operator+(const BigInteger& bi) const{
39         BigInteger temp;
40         temp.s.clear();
41         for (int i = 0,g = 0;;i++) {
42             
43             if (g == 0 && i >= s.size() && i >= bi.s.size()) break;
44             int x = g;
45             if (i < s.size()) x += s[i];
46             if (i < bi.s.size()) x += bi.s[i];
47             temp.s.push_back(x % BASE);
48             g = x / BASE;
49         }
50         return temp;    
51     }    
52     
53     BigInteger operator +=(const BigInteger& b) {
54         *this = *this + b;return *this;
55     }
56 };
57 
58 istream& operator >>(istream &in, BigInteger& x) {
59     string s;
60     if (!(in >>s)) return in;
61     x = s;
62     return in;
63 }
64     
65 ostream& operator <<(ostream &out, BigInteger&bi) {
66     out << bi.s.back();
67     for (int i = bi.s.size()-2; i >= 0; i--) {//再从倒数第二个输出 
68         char buf[20];
69         sprintf(buf, "%08d", bi.s[i]);
70         //cout << buf;
71         for (int j =0; j < strlen(buf); j++) out << buf[j];
72     }
73     return out;
74 }
75 
76 int main() {
77     int n;
78     BigInteger a,b,c;
79     cin >> n;
80     int kase = 1;
81     while (n) {
82         cin >> a >> b;
83         c = a + b;
84         if (n != 1)
85            cout <<"Case " << kase++ << ":" << "\n" << a << " + " << b << " = " << c << endl << endl;
86         else
87            cout <<"Case " << kase++ << ":" << "\n" << a << " + " << b << " = " << c << endl;
88         n--;
89     }
90     return 0;
91 }
(1)(2)略。
(3)分块处理的坑:

前面两个我就不总结了,这里主要说下,分块计算的坑。假设有这个字符串"123400000001",由于我们要将其
按照没8位字符分成一块所以第一块就是00000001、第二快就是1234,然后按照小端存储格式、低地址对应低位
但是但他们用sscanf格式化成整数时候,00000001不可能还是这样,这样就是八进制了,而是变成了1,所以我们
在输出的时候,除了最高位对应的那一块可能不足8位,剩下的块肯定都要8位处理,所以上面代码,才从第二快进行
输出,而且格式是%08d.
posted @ 2014-09-04 14:56 swp 阅读(1466) | 评论 (0)编辑 收藏

最近写程序的时候、碰到一个问题。其实就是将celing函数用C++默认的除法运算(向下取整)表示出来。所以我打算总结下整值函数。

Firth.首先我们要熟悉顶函数和底函数,最好的方式就是了解他们的图形。

由于数学符号在这里不好写出来,我们用floor来表示底,celing表示顶。

图形其实就是以f(x) = x 为分界线,这边就不画出来了。向下取整组成的坐标点就是(x, floor(x))

这些刚好就是在f(x) = x下方的,而向上取整则是在上方的。

Tips:

所以从图像中我们可以发现一下两个等式(位移、奇函数)

1.x – 1 < floor(x) <= x <= celing(x) < x + 1 (可以通过位移图像来得出该不等式)

2.floor(-x) = – celing(x) 或者 celing(-x) = – floor(x) (这个其实可以简单记为奇函数)

 

Second.两条法则(你要细分成4条我也不反对)

1.floor(x) = n 等价于 n <= x < n + 1 等价于 x – 1 < n <= x

2.celing(x) = n 等价于 n - 1 < x <= n 等价于 x <= n < x + 1

Tips:

1.其中n是整数,x是实数

2.floor(x + n) = floor(x) + n (因为有上面法则有 floor(x) + n <= x + n < floor(x) + n + 1).

3.但floor(nx) != n*floor(x)

 

Third.实数和整数之间的关系,其实都等价于一个顶或底函数于整数的关系。

1.x < n 等价于 floor(x) < n

2.n < x 等价于 n < celing(x)

3.x <= n 等价于 celing(x) <= n

4.n <= x 等价于 n <= floor(x)

Tips

1.celing相当于扩大、floor相当于缩小

2.取到n,则看能取到最大或者最小,最大取celing、最小floor。

   不达n,则缩小或扩大x等式不变。

3.floor(x + y) 等于 floor(x) + floor(y) 或者是 floor(x) + floor(y) + 1

   x = floor(x) + {x}, y = floor(y) + {y},then

   x + y = floor(x) + floor(y) + {x} + {y},then

   floor(x + y) = floor(x) + floor(y) + floor( {x} + {y})

   and because  0<={x} < 1 and so do {y},so

  0<={x} + {y} <2,so floor({x} + {y}) = 0 or 1

 

应用:

   在程序中应用之前,我先说下一个等式的证明

   celing(n / m) = floor( (n + m – 1) / m)

   这里n 、m都是整数,而且m是正整数。

证明:

    因为celing(n /m) – floor(n /m) = celing(n / m – floor(n / m))

    = celing(1/m * ( n – m*floor(n / m))) = celing((n mod m) / m)-------------(1)利用了上面两条法则中Tips的第二点

     同理可以得出floor((n + m –1) /m) = floor((n mod m + m – 1) / m)---------- (2)

   由(1)可以得到celing((n mod m )/ m) = 1

   由(2)可以得到floor((n mod m + m – 1) / m) = 1 (因为n mod m + m – 1 < 2 *m –1)

   所以可以一步步向上反推得到上面的公式。(其实这是一种分而自治的证明思想)

具体在程序中的应用例如:

当你要在C++中写如下代码时候,而且n 、m都是整数。

则celing(n * 1.0 / m) = floor( (n – 1) / m) + 1

由于C++中除运算就是向下取整,所以

celing(n * 1.0 / m) = (n - 1) / m + 1
那么什么地方用得到,比如你在做大数运算时侯,要进行,分组,要8位一组
然后算出一个可以分成几组。可以直接利用这个原理,而不用再其进行函数的
调用,比如你在阅读人家的代码时候、有时候就会这样写。

下次你碰到这种代码就会知道什么意思,和为什么能表示成这样了。

posted @ 2014-09-03 15:06 swp 阅读(1116) | 评论 (0)编辑 收藏

       现在已经大四上学期了、然而在我看到的很多人其实是充满了迷茫。根本不知道自己想要的是什么,也许这真的是教育的巨大失败。实习这个话题、有人认为要早早的去做为好,因为才能更快的接触社会经验,积累工作经验。在如今这个充满浮躁、毫无信仰的社会、在我看来什么时候去实习并不重要,不要为了学分而实习,因为你根本不知道你想要的是什么,就去盲目的追寻,但是这有时侯确实又是矛盾的。因为在你搞清楚你最想要的是什么,搞清楚你最想成为一个什么样的人并不是那么容易,因为感觉很多时候会欺骗你,只有你去尝试了、专注的去做了,才会知道自己真正喜欢的是什么。但是其实这些早在你在找实习之前就应该搞清除,你要了解你自己,而不是一头扎入社会、盲目而无信仰,可悲的是,如今有很多人确实如此,于是他们总觉得生活不如意、不知道为什么而活着、不知道未来究竟在哪里。为什么说大学里面是犯错的最好机会,我十分的赞成这种观点,虽然现在我自身也不是特别有成就的人,但是这句话的却是很有道理,大学里不是60分万岁、不是只是找个女朋友回去,搞不好还要奉子成婚的大学,大学是真正意义上的自我教育,更重要的是你要在大学里搞清除、想明白自己到底要做个什么样的人并为此打好基础,在这个搞清楚前,你需要不断的尝试、尝试各种方法。
      以我自身为例、在上大一时候,因为高中一直看些黑客技巧的小伎俩,所以在报考大学时当时我的想法就是,一定要报计算机类的,因为我喜欢它,确实我喜欢编程、我喜欢数学。大一时候,我一直在想要怎么样才能写个软件、我在想那么我得掌握什么、那时候没有认识的学长、没有人告诉我说,hello,你该怎么怎么办、再怎么怎么办、其实别人就算告诉你、在我看来也没有多大用处。因为每个人自身的条件和环境不可能完全一样,你不可能复制别人的成功来达到自己的成功,但是你可以学习别人成功方法,向他们看齐,所以大一一整年、我自己以为把算法数据结构搞定了、我就能写出牛逼的软件、哈哈,天真!。于是那一整年都泡在算法数据结构上、关键刚开始自学也是听痛苦的,主要原因是没有经验,竟然看了严蔚敏那本书,然后还没有人可以指导下、倒是那是能自己把你面到图部分的代码全部自己搞定、费了好大一把尽。当时就觉得,应该差不多了,可以去写软件了、、、唉、当时就是个菜逼。大一那时还十分积极很幸运的入选了ACM校队,不过我们学校的acm水平太菜了,但是这个经历对我后来学习算法有很大的帮助。然后来到大二偶然看到网上的直播课程、还是免费的、于是当时就心血来潮的去学习了、学了好大一年,觉得学了很多,但却没有底子。这就是我第一次犯的最大错误,为什么,因为当时我也不知道该怎么写软件,所以就只有去尝试、这个代价是花费了很长时间,我才明白这不是我想要的,但是我也学到了一些关于计算机的东西。接着迷迷糊糊的来到了大三,学了计算机网络、编译原理、操作系统等一些课程、其实当时我觉得这些课程这是他们的无聊枯燥、特别是网络、写得全都是背诵的,根本不知道怎么去实践、也就是在这个过程我又开始了自学、开始探索该怎么学习这些课程、在探索的过程、就慢慢的才了解到这些课程的内在、后来觉得这些课程真的是很有意思。但是呢,问题是等我探索完了、期末又来了,但是于此同时我对计算机和软件这门学科了解的更深了,因为我知道怎么去学。在大三下的时候,我就已经知道自己要怎么去学习这些课程、并且在这个过程我还自学了大量的数学知识、接触了大量程序的东西、就是因为有这些尝试、和真正的去做,我才越来越坚定自己能做什么,喜欢做什么,想要的是什么、其实前几年也不是白上的,只是学校教的毕竟有限,更多的是要自我教育。
      其实大学里,我们就应该好好珍惜时间,最简单的探索方法就是从大一一进来,你就去学习你感兴趣的专业、最重要的课程都认真的去学习,在这个自学的过程、你一定能搞找到很多你本来看不清楚的东西,当然你还要有一颗不放弃的心,因为这个过程不是那么的容易,但是当你做到了你会越来越明白自己想要的究竟是什么,想成为什么样的人,也许这个过程需要2年,也学需要3年,但请记住你在大学,尽管去需找,需找你人生的意思!。所以大学是犯错误和实践的最好的时间、不怕犯错、就怕连错误都不会犯,然后迷失掉自己。为了实习而实习,而且你进入社会第一家公司,对我们其实是十分重要的!
       之所以我打算工作一年期间考研究生(现在还在学习),一来是不打算再过度依赖父母,自己也挣点钱,二来是为了给自己3年来好好的沉淀下这些东西,研究生阶段、我一定天天都是高三、因为我知道自己要的是什么。此文送给哪些还在迷茫中的人,送给哪些还在大学里的人,如果你明白了、永远都不晚,努力去寻找,越早去寻找越好,也越能找到。
posted @ 2014-09-02 00:14 swp 阅读(209) | 评论 (0)编辑 收藏

由于是数学,所以要严谨。我们对于映射的概念直接摘抄来自同济大学的高数课本。
映射的概念:
设X和Y是两个非空的集合。存在一个法则T,使得X中的每个元素x按照法则T,在Y中都有一个唯一元素y与之对应。
那么T就称为X到Y的映射。记为T:X-->Y.
(1)X称为T的定义域、Y称为T的值域。而且y称为x的像,x称为原像。
(2)函数、算子、都是映射的别名。
Tips:
为了更好的理解、其实学过图论,就很好理解、可以把X看成起始点集合、Y看成终点集合、那么映射就是从起始点出发、都只有一条路径可以到对应的达终点(也就是说如果存在从某个起始点有两条路径可以到达不同的两个终点,就不叫映射)。
所以所谓的就是终点、原像就是起始点。

满射、单射、一一映射:
满射:在映射的概念下,不存在孤立的终点。(就相当于很多小岛,分为左右两半。左边的每个小岛都只有一座桥到达右边的一个小岛,不存在其它桥可以在去其它小岛,然后右边的小岛都有桥连接,这就叫满射)。
单射:单射就是不存在两个左边的小岛可以和右边的同一座小岛建立了桥。

一一映射:同时满足以上两个
严谨的数学定义:
设T是集合X到Y的映射,诺T(X)=Y,即Y中任一元素均是X中某元素的像,则陈T为X到Y上的满射。
对任意x1、x2属于X,x1 <>x2,必定有T(x1)<>T(x2),则陈T为X到Y上的单射。
一一映射:满足以上两个。

逆映射、复合映射:
这两个的数学定义就不讲了、去翻翻高数课本。主要总结下从离散化的图来理解的角度。
逆映射:也就是在一一映射的基础下,反客为主。把起始点变成终点、终点变成起始点。
复合映射:复合映射说的是在映射的基础下、对于第三方岛屿、右边的岛屿都有建桥到第三方的岛屿(右映射到第三方,但第三方可能存在孤岛)。则我们就可以把右边看作中间点、左边的岛屿也都有到第三方岛屿的路径。(左边映射到第三方
,但第三方可能存在孤岛

数学记号:
映射T的逆映射记为T(-1)(y) = x.
T1、T2两个映射复合映射记为:T2 。T1
上面句号是在正中间.
posted @ 2014-08-29 23:44 swp 阅读(606) | 评论 (0)编辑 收藏

最近在练习算法、觉得有必要总结下C++这方面的知识,C++确实是复杂,but i love it。
第一:运算符重载的基本应用。第二:运算符重载于友原函数的关系。第三:结构体于类关于运算符重载的区别。首先我需要普及下基本的知识:
预备知识operator(操作符)、operand(操作数)、表达式
表达式是由操作符和操作数构成的,而且一般每个表达式都有副作用,并且都有结果(关注结果和副作用)。什么意思?
关于副作用的理解:其实就是在达到结果的这个过程中所做的一些事情,而这些事情产生了一些影响,但是不影响结果。
好像有点绕、看看例子在理解吧。
看例子:
int a = 1,b=2,c; c = a + b;
在这段代码里面,c = a + b;就是表达式、其中 = 、 + 又称为操作符、c、a、b又称为操作数。其结果就是计算出了a+b的值,副作用没有。
又比如:
cout << "Helloe" << endl;其中 <<是操作符、cout、"helloe"、endl是操作数。<<的结果是返回了ostream的引用,而副作用就是将"Helloe"输出到屏幕。

第一:运算符重载的基本应用。
看如下代码:
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Point {
 6 private:
 7     double x,y;
 8 public:
 9     Point(double x = 0, double y = 0):x(x),y(y) {
10         
11     }
12     Point operator+(const Point &p) const{//这种是最基本的方式、其本质是做操作数调用operator+函数 
13         Point temp;
14         temp.x = this->x + p.x; 
15         temp.y = this->y + p.y;
16         return temp;
17     }
18     /*
19     ostream& operator<<(ostream& out) {
20         out << x << " " << y;
21         return out;
22     }
23     */
24     friend ostream& operator<<(ostream& out, Point & p);   
25 };
26 ///*
27 ostream& operator<<(ostream& out, Point & p) {
28     out << p.x <<" "<< p.y;
29     return out;
30 }
31 //*/
32 
33 int main() {
34     
35     Point a(1,5);
36     Point b(5,7);
37     Point c;
38     c = a + b;
39     //c << cout << endl;
40     cout << c << endl; 
41     return 0;
42 }
如上代码:
注释掉的先不用看,12--17行就是最基本的运算符重载、其调用在38行,本质是:c = a.operator+(b);也就是调用做操作数的方法那么还要友元函数干什么呢?考虑下输出,如果你想让cout对象能自动输出Point的对象如何半到。你很聪明一定想到重载<<运算符、yes!right!于是把operator<<作为成员函数,你只能写成上面注释掉的哪样,那么调用时,麻烦就来了、编程39行的样子。尼玛丫、真实变态、我是想让它是cout << c << endl。搞得四不像了。是的就是因为这样子不好用,所以我们要结合友元函数的技术和运算重载技术来实现40行的调用。好了重点来了!谨记之!
tips:对于非成员函数的运算符重载,第一个参数就是左操作数,第二个操作数就是右操作数。
第二:运算符重载和友原函数的关系
所以上面的友元函数的参数顺序是cout对象的引用是第一个参数、Point对象引用为第二个参数。
我们还要解决第二个问题,如何让这个函数访问Point对象的私有部分,只要在Point类中声明,hello我是你的朋友啦、他的东西就是你的啦、你要怎么用怎么用,这才是朋友么!不、是基友!我认为应该叫做基友函数,哈哈。声明格式就是加上friend和函数的声明即可。
tips:成员函数和非成员函数的运算符重载的区别就是,参数个数不一样。成员函数中的左操作数不用体现出来(用this即可)、而非成员函数的左右操作数都要体现在运算符函数参数里面。
第三:结构体和类关于运算符重载的区别
关于区别,其实只有一个,因为结构体默认的权限是public、即其成员对外界都是可见的,所以其不需要友元函数来支持,但是其还是需要用非成员函数来重载<<比较方便、而不是用成员函数来重载<<.原因上面已经说过了。注意这个原因不是友元这项技术体现出来的,而是成员函数和非成员函数体现出来的,友元技术知识用来支撑其在类中的应用。、
tips:对于结构体,非成员函数的运算符重载方法,不需要声明为友元函数。
如下代码:
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 struct Point{
 6     double x,y;
 7     Point(double x = 0, double y = 0):x(x),y(y) {
 8         
 9     }
10     Point operator+(const Point &p) const{//这种是最基本的方式、其本质是做操作数调用operator+函数 
11         Point temp;
12         temp.x = this->x + p.x; 
13         temp.y = this->y + p.y;
14         return temp;
15     }
16 };
17 
18 ostream& operator<<(ostream& out, Point & p) { 
19     out << p.x <<" "<< p.y;
20     return out;
21 }
22 
23 
24 int main() {
25     
26     Point a(1,5);
27     Point b(5,7);
28     Point c;
29     c = a + b;
30     cout << c << endl; 
31     return 0;
32 }
posted @ 2014-08-29 16:31 swp 阅读(2567) | 评论 (0)编辑 收藏

这是我自己总结的cocos2dx,方便自己查看和复习。所以不一定适合您。
//
//  ImageScene.h
//  sceneDemo
//
//  Created by sixleaves on 14-7-29.
//
//

#ifndef __sceneDemo__ImageScene__
#define __sceneDemo__ImageScene__

#include "cocos2d.h"
class ImageScene : public cocos2d::Layer
{

public:
    static cocos2d::Scene * createScene();
    virtual bool init();
    CREATE_FUNC(ImageScene);
};

#endif /* defined(__sceneDemo__ImageScene__) */
/*
 总结:
 知识点一:
 Scene场景类、Layer层的概念
 其实Scene是一对多得关系,一个场景类可以有多个Layer层。
 实质上Scene就是由Layer层构成的。他们的关系,你可以看成
 是树的结构,而且Scene和Layer都继承自Node类,所以其都
 能有addChild方法,所以Scene可以把Layer添加进去。
 
 知识点二:宏定义的两个应用
 1.在预编译时期的过滤应用(防御性措施)
 #ifndef __xxXXxxX_H__
 #define __xxXXxxX_H__
 insert #include code
 #endif
 这样在当包含两次时,就会过滤掉下一次包含。
 2.宏函数
 可以查看CREATE_FUNC的定义:
 如下
        #define CREATE_FUNC(__TYPE__) \
        static __TYPE__* create() \
        { \
        __TYPE__ *pRet = new __TYPE__(); \
        if (pRet && pRet->init()) \
        { \
        pRet->autorelease(); \
        return pRet; \
        } \
        else \
        { \
        delete pRet; \
        pRet = NULL; \
        return NULL; \
        } \
        }
“\”号的意义:首先宏函数其实本质上必须写成一行,
           而\只是在编程中对于不方便写在一行的代码的格式化
           它告诉编译器,我这一行还没结束,把下面的继续整合
           上来成为一行。而在此处,这样写是为了提高可读性。
该函数的作用:创建指定对象,并且调用这个对象的构造函数(init)。
 
知识点三:C++中的多态
对于同一个父类的类,调用的方法,取决于对象,这种形式的多态
需要将父类中相应地方法定义为virutal即可。其实这就是java
中的尽量使用借口引用的原因、其就是为了适应多态,区别在于C++
中比较啰嗦,而java是默认就是有virtual这种功能的。不用你再写
明。
所以为了能够在创建这个对象后调用其构造函数init。需要重写它
这就是为什么其父类将其声明为virtual的原因。至于createScene
纯粹就是工厂方法。
 
*/

createScene主要还是分别调用Scene类和自定义layer类的工厂方法create创建对象,让后将其添加到Scene对象中。
//
//  ImageScene.cpp
//  sceneDemo
//
//  Created by sixleaves on 14-7-29.
//
//

#include "ImageScene.h"
USING_NS_CC;

Scene * ImageScene::createScene() {
    auto scene = Scene::create();
    auto imageScene = ImageScene::create();
    scene->addChild(imageScene);
    return scene;
}


bool ImageScene::init() {
    Size size = Director::getInstance()->getVisibleSize();
    auto sprite = Sprite::create("CloseSelected.png");
    sprite->setPosition(size.width/2, size.height/2);
    addChild(sprite);
    return true;
}
posted @ 2014-07-30 15:49 swp 阅读(269) | 评论 (0)编辑 收藏

仅列出标题
共10页: First 2 3 4 5 6 7 8 9 10