存档

‘C&&C++’ 分类的存档

Divide And Conquer

2011年9月2日 Jarod Lee 没有评论

Merge Sort:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void Merge(int list[], int lowIndex, int highIndex, int midIndex)
{
   int *tempList = new int[highIndex-lowIndex+1];
   int firstLow = lowIndex;
   int secondLow = midIndex + 1;
   int index = 0;
   while(firstLow <= midIndex && secondLow <= highIndex)
   {
      if (list[firstLow] < list[secondLow])
         tempList[index++] = list[firstLow++];
      else
         tempList[index++] = list[secondLow++];
   }

   while (firstLow <= midIndex)
   {
      tempList[index++] = list[firstLow++];
   }

   while (secondLow <= highIndex)
   {
      tempList[index++] = list[secondLow++];
   }

   for (int ii = 0; ii < index; ii++)
   {
      list[lowIndex+ii] = tempList[ii];
   }
   delete[] tempList;
}

void MergeSort(int list[], int lowIndex, int highIndex)
{
   if (lowIndex < highIndex)
   {
      int midIndex = lowIndex + (highIndex-lowIndex)/2;
      MergeSort(list, lowIndex, midIndex);
      MergeSort(list, midIndex+1, highIndex);
      Merge(list, lowIndex, highIndex, midIndex);
   }
}
分类: C&&C++, Programming 标签:

Recursion

2011年9月1日 Jarod Lee 没有评论

递归生成某集合的所有序列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
template <class T>
void Swap(T& a, T& b)
{
   T temp = a;
   a = b;
   b = temp;
}

template <class T>
void Permulation(T list[], int k, int m)
{
   if (k == m)
   {
      for (int i = 0; i <= m; i++)
         cout << list[i];
      cout << endl;
   }
   else
   {
      for (int i = k; i <= m; i++)
      {
         Swap(list[k], list[i]);
         Permulation(list, k+1, m);
         Swap(list[k], list[i]);
      }
   }
}

递归生成某集合的所有子集:

思想:
设集合X (A1, A2, A3,…, An)的所有子集为S[X(n)],从集合X中移走A1的子集X(n-1)的所有子集集合记为S[X(n-1)]
S[X(n)] = S[X(n-1)] ∪ {S[X(n-1)]每个子集加上A1}
例如 集合{A, B, C}
{A}:
{} {A}
{A B}:
{} {A} ∪ {B} {A B}
{A B C}:
{} {A} {B} {A B} ∪ {C} {A C} {B C} {A B C}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <class T>
void FindSubSets(T list[], int lowIndex, int highIndex, vector< set<T> > &results)
{
   if (lowIndex == highIndex)
   {
      set<T> empty;
      set<T> oneElem;
      oneElem.insert(list[lowIndex]);
      results.push_back(empty);
      results.push_back(oneElem);
   }
   else
   {
      FindSubSets(list, lowIndex+1, highIndex, results);
      int existedSetSize = results.size();
      for (int jj = 0; jj < existedSetSize; jj++)
      {
         set<T> newSet(results[jj]);
         newSet.insert(list[lowIndex]);
         results.push_back(newSet);
      }
   }
}

斐波那契数列计算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
递归:
int r_Fibonacci(int n)
{
   if ( n < 2)
      return n;
   return r_Fibonacci(n-1) + r_Fibonacci(n-2);
}

非递归:
int fibonacci(int n)
{
   if ( n < 2)
      return n;
   int f0 = 0;
   int f1 = 1;
   for (int ii = 1; ii < n; ii++)
   {
      f1 = f1 + f0;
      f0 = f1 - f0;
   }
   return f1;
}

递归查找:

1
2
3
4
5
6
7
8
template <class InputIter, class T>
InputIter find(InputIter begin, InputIter end, const T& val)
{
   if (begin != end && *begin != val)
      return find(begin+1, end, val);
   else
      return begin;
}
分类: C&&C++ 标签:

3N+1

2011年8月31日 Jarod Lee 没有评论
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int threeN(int n)
{
   if (n%2==0)
      return n/2;
   else
      return n*3+1;
}

int getLength(int n)
{
   static map<int, int> history;
   int key = n;
   
   if (n == 1)
      return 1;

   if (history.find(key) != history.end())
      return history[key];

   int length = getLength(threeN(n))+1;
   history[key] = length;
   return length;
}
分类: C&&C++, Programming 标签:

链表

2011年8月18日 Jarod Lee 没有评论

1. 逆转链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef struct Node
{
   int Data;
   Node *Next;
};

Node *ReverseList(Node *pHead)
{
   Node *pReverseHead = NULL;
   while (pHead != NULL)
   {
      Node *pTmp = pHead;
      pHead = pHead->Next;
      pTmp->Next = pReverseHead;
      pReverseHead = pTmp;
   }
   return pReverseHead;
}

bool hasCircle(Node *pHead)
{
   Node *pSlow = pHead;
   Node *pFast = pHead;
   while (pSlow && pFast && (pFast=pFast->Next) && pFast!=pSlow)
   {
      pSlow=pSlow->Next;
      pFast=pFast->Next;
   }
   return pFast != NULL;
}
分类: C&&C++, Programming 标签:

设计类时要考虑的问题

2011年8月9日 Jarod Lee 没有评论

1. 你的类需要构造函数吗?其访问控制级别怎样?

2. 数据成员需要设计成私有的吗?

3. 需要无参的构造函数吗?

4. 需要析构函数吗?需要设计成虚析构函数吗?

5. 需要复制构造函数吗

如果在构造函数中分配资源,则需要复制构造函数

6. 需要赋值操作符吗?

检查自我赋值

释放旧值, 复制新值

7. 需要定义关系运算符吗?

8. 参数类型需要加上 const 吗?

9. 成员函数需要时 const 吗?

分类: C&&C++, Programming 标签:

引用与指针的区别

2010年11月22日 Jarod Lee 没有评论

指针和引用都是用来间接访问对象的,他们之间有什么区别呢?何时用指针?何时用引用?为什么?

1. 首先认识到指针可以初始化为NULL而引用则不可以。 一个引用变量必须引用到某个对象上, 而且一旦初始化一个引用后,这个引用只能访问这个对象,而不能重新给该引用赋值到其他对象,即关系一旦建立,就不能解除。 因此当你需要一个变量可以间接访问其他对象时, 你需要使用指针。

因为一个引用必须关联到某个对象, 因为在定义引用时必须初始化:
string &rs; // 错误: 引用变量必须初始化
string s(“xyzzy”);
string &rs = s; // okay, rs引用s

指针没有这个限制:
string *ps; // 未初始化的指向string的指针

2. 指针可以重新指向其他的对象, 引用只能指向他初始化的对象,可以说引用像一个指针常量。

分类: C&&C++ 标签:

C++ Best Practice

2010年11月17日 Jarod Lee 没有评论

Watch out for bugs introduced in the constructor of base and other parent classes. Make sue an object is fully constructed before calling any virtual function.

在基类的构造函数中调用虚函数很容易引起bug,因为在构造派生类对象的时候先调用基类的的构造函数,因为此时派生类对象还没有构造完全,如果基类中的虚函数在派生类中重写了,那么基类不会调用这些虚函数,而是调用中的虚函数实现, 很容易引起bug。

分类: C&&C++, Programming 标签:

理解C/C++语言声明的优先级规则

2010年11月9日 Jarod Lee 没有评论

A 声明从它的名字开始读取,然后按照优先级顺序依次读取
B 优先级从高到底依次是

  • 声明中被括号括起来的那一部分
  • 后缀操作符: 括号()表示这是一个函数,而方括号[]表示这是一个数组
  • 前缀操作符: 星号 * 表示“指向...的指针”

C 如果const和(或) volatile关键字后面紧跟类型说明符(如int,long等), 那么它作用于类型说明符,在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

例如, 声明 char * const *(*next)();
A     首先变量名为“next”, 并注意到它直接被括号括住
B.1  把括号里作为一个整体,得出“next是指向…的指针”
B     考虑括号外面的东西, 在星号*前缀和()后缀间作选择,根据优先级规则,()优先级较高,所以next是一个函数指针,指向一个返回…的函数
B.3  处理前缀“*”, 得出指针所指的内容
C     最后把char * const解释为指向字符的常量指针

根据分析可以概括出: next是一个指针,它指向一个函数,该函数的参数列表为空,并返回一个指针,返回的指针指向一个类型为指向char的常量指针。

分类: C&&C++, Programming 标签:

A Reference Takes its Own Space in Memory,引用不是变量的别名,本质上是一个指针常量,存储变量的地址

2010年10月13日 Jarod Lee 没有评论

通过地下的例子可以证明,引用不是一个别名,他拥有自己独立的内存空间。 检验一个只含有引用数据成员的类的大小,就可以证明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
class Test
{
   int &i; // int *const i;
   int &j; // int *const j;
   int &k; // int *const k;
};

int main()
{
   // This will print 12 i.e. size of 3 pointers
   cout<< “size of class Test =<< sizeof(class Test) << endl;
   return 0;
}
分类: C&&C++ 标签:

函数指针定义解读

2010年9月19日 Jarod Lee 没有评论

原则:从中间开始到两边结束
中间开始指的是从中间定义的变量开始,
到两边结束:指的是从中间变量开始先右后左的原则依次解读
sample: void (*pFuncPtr)()
中间开始:定义一个pFuncPtr,
先右后左,右边是个右括号,忽略之, 左边是个*说明pFuncPtr是个指针,然后右边是个(), 说明指针指向一个没有参数的函数,然后在左边是void说明指向
的函数的返回类型是void

“从中间开始” (pFuncPtr是一个…), 到右边(无意义的右括号), 左边“*”(指针,指向。。。), 右边-空的参数列表(“ 一个没有参数的函数),
左边void(pFuncPtr是一个指针, 指向带无参的返回类型为void函数)

void *pFuncPtr()
pFuncPtr是一个没有参数的函数,返回类型为void*

复杂的声明和定义
1。 void * (*(*fp1)(int))[10]

fp1是一个函数指针, 指向点一个int参数的函数,该函数返回一个指针,该指针指向一个有10个void*指针元素的数组

2. float (*(*fp2)(int, int, float))(int);

fp2是一个函数指针,指向一个参数列表为(int, int, float)的函数,该函数返回一个函数指针,指向一个参数为(int)返回类型为float的指针

3. typedef double (*(*(*fp3)())[10])();
fp3 a;
fp3是一个函数指针指向一个无参的函数, 返回类型是一个指针,指向一个有十个数组的元素,其中每个元素是一个函数指针指向一个没有参数的返回类型
为double的函数

4 int (*(*f4())[10])();
f4是一个函数返回一个指针,指向一个有十个元素的数组,每个数组元素为一个函数指针,指向一个带无参返回类型为int的函数

分类: C&&C++ 标签: