« February 2006 | Main | April 2006 »

March 31, 2006

找出单向链表的中间结点

这道题和解判断链表是否存在环,我用的是非常类似的方法,只不过结束循环的条件和函数返回值不一样罢了。设置两个指针p1,p2。每次循环p1向前走一步,p2向前走两步。当p2到达链表的末尾时,p1指向的时链表的中间。

link* mid(link* head)
{
	link* p1,*p2;
	p1=p2=head;
	if(head==NULL || head->next==NULL)
		return head;
	do {
		p1=p1->next;
		p2=p2->next->next;
	} while(p2 && p2->next);
	return p1;
}

平面体检一百关

这里看到的,蛮实用的,就摘了下来,看看你能过几关。身体还是革命的本钱啊,大家注意自己的身体哦。

粉色题板
1. 每周一次晨爱
2. 在干净的床上裸睡()
3. 生理期不吃巧克力,因为会加重痛经
4. 经期只穿无钢圈内衣
5. 养成记录生理周期的习惯
6. 通过运动而非调整型内衣来塑造曲线
7. 不翘二郎腿,以免压迫神经
8. ML后去一次洗手间
9. 贴身衣物不干洗
10. 拉风的丁字裤不适宜日常穿着
11. 不穿标有“免烫”标识的衣服
12. 丝巾扎得过紧会导致头晕
13. 去年的衣服要进行曝晒后才可以穿
14. 如非必要,不使用卫生护垫
15. 定期检查化妆品的保质期
16. 洗浴后一小时再化妆
17. 每周只用一次清洗液,用温水清洁私密部位
18. 即使爱美,也不要在耳朵上部的外缘软骨部位穿耳洞
19. 染发频率控制在半年一次
20. 了解自己的家庭病史,特别是母亲和外婆的病史

蓝色题板
21. 每天踏进办公室,先将窗户打开透气,再坐下来工作
22. 如果一天要接听5小时电话,使用无线耳机
23. 复印文件时,与复印机保持至少一米
24. 只在非常必要时才使用滴眼液
25. 不趴在办公桌上午睡
26. 该午休的时候不玩电脑游戏
27. 在办公室为自己准备小靠垫,放在腰部
28. 从不戴着眼镜接听手机
29. 别让电脑包围你,它的侧、背面辐射更凶
30. 不要将笔记本电脑放在膝上使用
31. 在办公桌上养一盆仙人掌,帮助吸收辐射
32. 阅读完报纸后,记得清洗掉沾在手上的油墨
33. 每30分钟伸一次懒腰
34. 办公室地毯定期清洗杀虫
35. 用完电脑后要清洁面部及手部,清除辐射微尘
36. 下班时将洗净的水杯倒扣在办公桌上
37. 单肩的短带挎包会加重肩周炎症状
38. 公文包时的口红与签字笔分格存放
39. 每天保证有2小时以上的时间,让脚从高跟鞋时解放出来
40. 每周晚过22:00的加班不超过一次


绿色题板
41. 浴室保持干燥,防止霉菌滋生
42. 沐浴不超过10分钟
43. 不要坐在马桶上看报纸
44. 用温水刷牙,同时刷刷舌头
45. 用冷热水交替洗脸
46. 不用塑料器皿盛装热水
47. 定期清理冰箱
48. 微波炉在工作时,请离开厨房
49. 使用抽油烟机
50. 晚餐时关掉电视机
51. 尽量避免使用厚绒布窗帘
52. 杀虫剂和清洁剂要放在远离起居场所的储物间
53. 用天然的花香或果香代替芳香剂
54. 和宠物嬉戏完要认真洗手
55. 冬天居室里的加湿器使用纯净水
56. 不要贪图方便将电脑带进卧室
57. 不要把手机放在枕边充当闹钟
58. 别在临睡前服药,安眠药也要提前半小时服用
59. 头发没干时,别急着入睡
60. 卧室的房间要用柔和色彩


黄色题板
61. 在牛奶和豆浆之间,选择后者
62. 觉得还可以再吃半碗饭时,离开餐桌
63. 如果身体不感到饥渴,每天只需饮用4杯水
64. 多喝酸奶
65. 无论什么原因,都别抽烟
66. 在食谱里添加杂粮和蔬菜
67. 饮绿茶胜过红茶
68. 重视早餐多过晚餐
69. 控制盐的用量
70. 起床后先刷牙,再喝水
71. 经常嚼口香糖
72. 一早一晚,两个苹果可以有效改善便秘
73. 纯素食可能导致荷尔蒙分泌异常,造成不孕
74. 每周至少吃一次鱼
75. 远离可乐等碳酸饮料
76. 不喝久煮的火锅汤
77. 没有果汁牛奶这回事,它们是天生的冤家
78. 饭前吃水果胜过饭后
79. 睡前可以来一杯红葡萄酒
80. 喝咖啡可能引起女性骨质疏松


橙色题板
81. 多享受早晨8-9点的阳光
82. 跑步、骑脚踏车等运动可以保持优美的腿部线条
83. 热水泡脚可有效预防静脉曲张
84. 精神极度疲倦时并不适宜以运动减压,休息更重要
85. 冬季少做户外运动
86. 10层以下,不乘坐电梯
87. 每三个月改变一次你的健身菜单
88. 每天运动半小时,而非周末运动3小时
89. 运动前先卸妆
90. 边看电视边做柔软体操
91. 在游泳池里一定要戴上泳帽和泳镜
92. 经常散步
93. 午休也是健身的好时间,不一定非等到晚上
94. 光脚穿运动鞋固然舒服,却对健康不利
95. 睡半硬的床铺更有利于颈椎健康
96. 去正规的医院而非美容院接受按摩
97. 非运动状态下不喝功能性饮料
98. 运动后休息半小时再入浴
99. 不在过吵的健身房中锻炼
100. 正确的姿势比专程去健身更有效

按单词反转字符串

并不是简单的字符串反转,而是按给定字符串里的单词将字符串倒转过来,就是说字符串里面的单词还是保持原来的顺序,这里的每个单词用空格分开。例如:
Here is www.zhuxinquan.com
经过反转后变为:
www.zhuxinquan.com is Here
如果只是简单的将所有字符串翻转的话,可以遍历字符串,将第一个字符和最后一个交换,第二个和倒数第二个交换,依次循环。其实按照单词反转的话可以在第一遍遍历的基础上,再遍历一遍字符串,对每一个单词再反转一次。这样每个单词又恢复了原来的顺序。

char* reverse_word(const char* str)
{
     int len = strlen(str);
     char* restr = new char[len+1];
     strcpy(restr,str);
     int i,j;
     for(i=0,j=len-1;i<j;i++,j--)
     {
          char temp=restr[i];
          restr[i]=restr[j];
          restr[j]=temp;
     }
     int k=0;
     while(k<len)
     {
          i=j=k;
          while(restr[j]!=' ' && restr[j]!='\0' )
               j++;
          k=j+1;
          j--;
          for(;i<j;i++,j--)
          {
               char temp=restr[i];
               restr[i]=restr[j];
               restr[j]=temp;
          }
     }
     return restr;
}

如果考虑空间和时间的优化的话,当然可以将上面代码里两个字符串交换部分改为异或实现。
例如将

 
          char temp=restr[i];
          restr[i]=restr[j];
          restr[j]=temp;


改为

 
          restr[i]^=restr[j];
          restr[j]^=restr[i];
          restr[i]^=restr[j];

March 30, 2006

判断链表是否存在环

问题:判断一个链表是否存在环,例如下面这个链表就存在一个环:
例如N1->N2->N3->N4->N5->N2就是一个有环的链表,环的开始结点是N5

这里有一个比较简单的解法。设置两个指针p1,p2。每次循环p1向前走一步,p2向前走两步。直到p2碰到NULL指针或者两个指针相等结束循环。如果两个指针相等则说明存在环。

struct link {
    int data;
    link* next;
};

bool IsLoop(link* head)
{
    link* p1=head, *p2 = head;
	if (head ==NULL || head->next ==NULL) {
		return false;
	}
    do{
        p1= p1->next;
        p2 = p2->next->next;
    } while(p2 && p2->next && p1!=p2);     
	if(p1 == p2)
		return true;
	else
		return false;
}

March 28, 2006

XML初探(一)

趁工作的空闲时间,随手拿了一本Erik T. Ray写的 《Learning XML》 翻了一下。一直想了解一下XML,确苦于没有时间。还有就是技术这个东西,你学了不用,过了一段时间就会全部忘光光。可惜我的项目用不到XML,不过反正没事,就看了一个下午,觉得容易忘记的一些东西记了一点下来。

Elements, attributes, namespaces, and entities are the most important markup objects in XML.

保留属性
XML可以定义自己的元素(element)包括这个元素的属性,但下没保留的元素属性不能重新定义:
xml:lang
Classifies an element by the language of its content. For example, xml:lang="en" describes an element
as having English content. This is useful for creating conditional text, which is content selected by an
XML processor based on criteria such as what language the user wants to view a document in. We'll
return to this topic in Chapter 7.
xml:space
Specifies whether whitespace should be preserved in an element's content. If set to preserve, any XML
processor displaying the document should honor all newlines, spaces, and tabs in the element's
content. If it is set to default, then the processor can do whatever it wants with whitespace (i.e., it
sets its own default). If the xml:space attribute is omitted, the processor preserves whitespace by
default. Thus, if you want to compress whitespace in an element, set the attribute xml:space="default"
and make sure you are using an XML processor whose default is to remove extra whitespace.
xml:link
告诉 XLink processor 这是一个xlink element。相当于HTML里面的超链接
xml:attribute
In addition to xml:link, XLink relies on a number of attribute names. But to prevent conflict with other
potential uses of those attributes, XLink defines the xml:attribute attribute, which allows you to
"remap" those special attributes. That is, you can say, "When XLink is looking for an attribute called
title, I want you to use the attribute called linkname instead." This attribute is also discussed in more
detail in Chapter 3.
名字空间 (namespace)
名字空间是属性和元素的集合,为了解决元素和属性的名字冲突的问题,XML也有命名空间。处于不用的名字空间的元素和属性的名字可以不同。名字空间声明在一个某一个element中,所有被这个element包含的element都将属于这个名字空间
例如下面的例子声明了一个名字空间bob,并且告诉XML parser 这里有一个名字空间的属性

 <part-catalog xmlns:bob="http://www.bobco.com/"> 

实体 (entity)
实体是XML内容中的占位符(placeholder),一旦你定义一个实体后,接下来就可以用这个实体标识符在XML文档里来表示相同的内容。例如下面的文档定义了一个client 实体。在文档中,&client; 引用了该实体。

<?xml version="1.0"?>
<!DOCTYPE message SYSTEM "/xmlstuff/dtds/message.dtd"
[
<!ENTITY client "Mr. Rufus Xavier Sasperilla">
]>
<message>
<opening>Dear &client;</opening>
<body>We have an exciting opportunity for you! 
</body>
</message>

在XML中有多种实体。

March 27, 2006

删除数组中重复的数字

问题:一个动态长度可变的数字序列,以数字0为结束标志,要求将重复的数字用一个数字代替,例如:
将数组 1,1,1,2,2,2,2,2,7,7,1,5,5,5,0 转变成1,2,7,1,5,0

问题比较简单,要注意的是这个数组是动态的。所以避免麻烦我还是用了STL的vector。

#include <iostream>
#include <vector>
using namespace std;
//remove the duplicated numbers in an intger array, the array was end with 0;
//e.g. 1,1,1,2,2,5,4,4,4,4,1,0 --->1,2,5,4,1,0
void static remove_duplicated(int a[], vector<int>& _st)
{
	_st.push_back(a[0]);
	for(int i=1;_st[_st.size()-1]!=0;i++)
	{
		if(a[i-1]!=a[i])
			_st.push_back(a[i]);
	}
}

当然如果可以改变原来的数组的话,可以不用STL,仅需要指针操作就可以了。下面这个程序将修改原来数组的内容。

void static remove_duplicated2(int a[])
{
	if(a[0]==0 || a==NULL)
		return;
	int insert=1,current=1;
	while(a[current]!=0)
	{
		if(a[current]!=a[current-1])
		{
			a[insert]=a[current];
			insert++;
			current++;
		}
		else
			current++;
	}
	a[insert]=0;
}

字符串反转

我没有记错的话是一道MSN的笔试题,网上无意中看到的,拿来做了一下。题目是这样的,给定一个字符串,一个这个字符串的子串,将第一个字符串反转,但保留子串的顺序不变。例如:
输入: 第一个字符串: "This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn"
子串: "zhuxinquan"
输出: "nc/moc.zhuxinquan.www//:ptth :etis esenihC s'zhuxinquan si sihT"
一般的方法是先扫描一边第一个字符串,然后用stack把它反转,同时记录下子串出现的位置。然后再扫描一遍把记录下来的子串再用stack反转。我用的方法是用一遍扫描数组的方法。扫描中如果发现子串,就将子串倒过来压入堆栈。
最后再将堆栈里的字符弹出,这样子串又恢复了原来的顺序。源代码如下:

#include <iostream>
#include <cassert>
#include <stack>
using namespace std;
//reverse the string 's1' except the substring 'token'.
const char* reverse(const char* s1, const char* token)
{
	assert(s1 && token);
	stack<char> stack1;
	const char* ptoken = token, *head = s1, *rear = s1;
	while (*head != '\0')
	{
		while(*head!= '\0' && *ptoken == *head)
		{
			ptoken++;
			head++;
		}
		if(*ptoken == '\0')//contain the token
		{
			const char* p;
			for(p=head-1;p>=rear;p--)
				stack1.push(*p);

			ptoken = token;
			rear = head;
		}
		else
		{
			stack1.push(*rear);
			head=++rear;
			ptoken = token;
		}
	}
	char * return_v = new char[strlen(s1)+1];
	int i=0;
	while(!stack1.empty())
	{
		return_v[i++] = stack1.top();
		stack1.pop();
	}
	return_v[i]='\0';
	return return_v;
}
int main(int argc, char* argv[])
{
	
	cout<<"This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn\n";
	cout<<reverse("This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn","zhuxinquan");
	return 0;
}

如何判断一棵二叉树是否是平衡二叉树

问题:判断一个二叉排序树是否是平衡二叉树
这里是二叉排序树的定义
解决方案:
根据平衡二叉树的定义,如果任意节点的左右子树的深度相差不超过1,那这棵树就是平衡二叉树。
首先编写一个计算二叉树深度的函数,利用递归实现。

template<typename T>
static int Depth(BSTreeNode<T>* pbs)
{
	if (pbs==NULL)
		return 0;
	else
	{
		int ld = Depth(pbs->left);
		int rd = Depth(pbs->right);
		return 1 + (ld >rd ? ld : rd);
	}
}

下面是利用递归判断左右子树的深度是否相差1来判断是否是平衡二叉树的函数:

template<typename T>
static bool isBalance(BSTreeNode<T>* pbs)
{
	if (pbs==NULL) 
		return true;
	int dis = Depth(pbs->left) - Depth(pbs->right);
	if (dis>1 || dis<-1 )
		return false;
	else
		return isBalance(pbs->left) && isBalance(pbs->right);
}

March 14, 2006

strstr()的简单实现

strstr(s1,s2)是一个经常用的函数,他的作用就是在字符串s1中寻找字符串s2如果找到了就返回指针,否则返回NULL。
下面是这个函数的一个简单实现:
static const char* _strstr(const char* s1, const char* s2)
{
     assert(s2 && s1);
     const char* p=s1, *r=s2;
     while(*p!='\0')
     {
          while(*p++==*r++);
          if(*r=='\0')
               return p;
          else
          {
               r=s2;
               p=++s1;
          }
     }
     return NULL;
}

March 09, 2006

电影中常用的口语表达

沪江BBS上看到的,比较有意思,摘了一部分我不怎么熟的短语过来。
I‘ve seen this moment in my dreams 我已经在梦中见到这一刻了
with one's name on one's lips 嘴边常念某人的名字
Be well 保重
let this go 忘掉此事
What's going on? 怎么回事
I don't have time to waste 我没空
back in a sec 很快回来
good point 说得好
get in position,please 各就各位
such is life 这就是人生
There's nothing either of us can do 我们都无能为力
Just forget this business 忘了这件事吧
I run out of words 我欲语无言
I'm as ever 我一如既往
forget about it 算了吧
No big deal 没什么大不了的
go to hell 去死吧(骂人的话)
destiny takes a hand 命中注定
No way 不行
see what I mean? 懂吗
I'm willing to get to the bottom of it 我想搞清楚这件事