第一题:通过键盘输入一串小写字母(a~z)组成的字符串。请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。
压缩规则:
1、仅压缩连续重复出现的字符。比如字符串"abcbc"由于无连续重复字符,压缩后的字符串还是"abcbc"。
2、压缩字段的格式为"字符重复的次数+字符"。例如:字符串"xxxyyyyyyz"压缩后就成为"3x6yz"。
下面是我写的代码:
1 #include <iostream> 2 3 using namespace std; 4 5 void stringZip(const char *pInputStr,long linputLen,char *pOutputStr) 6 { 7 char ccount = '0'; 8 int i = 0; 9 const char *pPoint1 = pInputStr; 10 const char *pPoint2 = pInputStr; 11 12 //判断指针是否为空 13 if(pInputStr == NULL) 14 { 15 pOutputStr = NULL; 16 return ; 17 } 18 for(i=0;i < linputLen;) 19 { 20 ccount = '0'; 21 while((*pPoint1)==(*pPoint2)) 22 { 23 i++; //控制循环 24 ccount ++; 25 pPoint2 ++; 26 } 27 //跳出循环赛说明两个指针所指的字符开始不相等 28 if(ccount > '1') *pOutputStr++ = ccount; 29 *pOutputStr++ = *pPoint1; 30 pPoint1 = pPoint2; 31 } 32 *pOutputStr = '\0'; 33 } 34 35 int main() 36 { 37 char *pOutputStr = (char *)malloc(sizeof(char)*20); 38 char *pInputStr = "Hello,world!"; 39 stringZip(pInputStr,strlen(pInputStr),pOutputStr); 40 cout << "Output:" << pOutputStr << endl; 41 return 0; 42 }
好久没写代码了,这次写代码犯了几个错误:
1.sizeof和strlen计算字符串大小出来的结果是不一样的。
2.非C语言风格的字符串用cout打印出来会乱码。
3.居然这样p = '\0'给p所指向的内容赋值。
第二题:已知memcpy的函数为: void* memcpy(void *dest , const void* src , size_t count)其中dest是目的指针,src是源指针。不调用c++/c的memcpy库函数,请编写memcpy。
下面是参考代码:
1 void* memcpy_(void *dest , const void* src , size_t count) 2 { 3 //安全检查 4 assert(dest != NULL && src != NULL); 5 unsigned char *pdest = (unsigned char *)dest; 6 const unsigned char *psrc = (const unsigned char *)src; 7 8 assert(!(psrc <= pdest && pdest < psrc+count)); 9 assert(!(pdest<= psrc && psrc < pdest+count)); 10 while(count--) 11 { 12 *pdest = *psrc; 13 pdest++; 14 psrc ++; 15 } 16 return dest; 17 } 18 19 int main() 20 { 21 char *pOutputStr = (char *)malloc(sizeof(char)*20); 22 char dest[] = "abcdefgh"; 23 char *src = "123456"; 24 memcpy_(dest,src,2); 25 cout << "Output:" << dest << endl; 26 return 0; 27 }
这题我做的不对,没做防止内存重复的检查,其次又遇到了几个问题:
1.char *str = "Hello,world!";是个字符串常量,不能对其赋值。
2.不能对void * 指针进行算术操作,会报unknow size的错
第三题:已知集合A和B的元素分别用不含头结点的单链表存储,函数difference()用于求解集合A与B的差集,并将结果保存在集合A的单链表中。例如,若集合A={5,10,20,15,25,30},集合B={5,15,35,25},完成计算后A={10,20,30}。
我的代码如下(只有函数):
1 struct node 2 { 3 int elem; 4 node* next; 5 }; 6 //LA,LB是集合,不存在重复元素 7 void difference(node** LA , node* LB) 8 { 9 //安全检查 10 node *lpB = LB,*lpA1 = *LA,*lpA2 = *LA; 11 assert((LB != NULL)&&(* LA) != NULL); 12 //如果是用一般的方法,复杂度是O(m*n) 13 while(lpA2 != NULL) 14 { 15 lpB = LB; 16 while(lpB != NULL) 17 { 18 if(lpA2 == (*LA)) //如果是首节点 19 { 20 if(lpB->elem == lpA2->elem) 21 { 22 *LA = (*LA)->next; //将首节点指向下一个 23 free(lpA2); //释放被删除的节点 24 lpA1 = lpA2 = *LA; //重新指向 25 } 26 else 27 { 28 lpA2 = lpA1->next; 29 } 30 } 31 else 32 { 33 if(lpB->elem == lpA2->elem) 34 { 35 lpA1 = lpA2->next; 36 free(lpA2); 37 lpA2 = lpA1->next; 38 } 39 { 40 lpA1 = lpA2; 41 lpA2 = lpA2->next; 42 } 43 } 44 } 45 } 46 }
第四题:把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16 转换成双向链表 4=6=8=10=12=14=16。 首先我们定义的二元查找树节点的数据结构如下:
struct BSTreeNode {
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
代码如下如下,参考:http://blog.csdn.net/v_JULY_v/article/details/6126406
1 #include <iostream> 2 3 using namespace std; 4 5 struct BSTreeNode //二元查找树的节点 6 { 7 int m_nValue; 8 BSTreeNode *m_pLeft; 9 BSTreeNode *m_pRight; 10 }; 11 typedef BSTreeNode DoubleList; 12 DoubleList *pHead = NULL; 13 DoubleList *pIndex = NULL; 14 //创建二元查找树 15 void addBSTreeNode(BSTreeNode *&pCurrent,int value) 16 { 17 if(NULL == pCurrent) //如果是空的话就创建节点 18 { 19 BSTreeNode *pBSTree = new BSTreeNode(); 20 pBSTree->m_pLeft = NULL; 21 pBSTree->m_pRight = NULL; 22 pBSTree->m_nValue = value; 23 pCurrent = pBSTree; 24 } 25 else 26 { 27 if(pCurrent->m_nValue > value) 28 { 29 addBSTreeNode(pCurrent->m_pLeft,value); 30 } 31 else if(pCurrent->m_nValue < value) 32 { 33 addBSTreeNode(pCurrent->m_pRight,value); 34 } 35 else 36 { 37 cout << "重复插入"; 38 } 39 } 40 41 } 42 43 //遍历二元查找树 中序 44 void inorderBSTree(BSTreeNode *pCurrent) 45 { 46 if(NULL == pCurrent) 47 { 48 return ; 49 } 50 else 51 { 52 inorderBSTree(pCurrent->m_pLeft); 53 { 54 if(NULL == pHead) 55 { 56 pHead = pCurrent; //首节点 57 pIndex= pCurrent; 58 } 59 else 60 { 61 pIndex->m_pRight = pCurrent; 62 pCurrent->m_pLeft= pIndex; 63 pIndex = pCurrent; 64 } 65 } 66 inorderBSTree(pCurrent->m_pRight); 67 } 68 } 69 70 int main() 71 { 72 BSTreeNode * pRoot = NULL; 73 addBSTreeNode(pRoot, 10); 74 addBSTreeNode(pRoot, 4); 75 addBSTreeNode(pRoot, 6); 76 addBSTreeNode(pRoot, 8); 77 addBSTreeNode(pRoot, 12); 78 addBSTreeNode(pRoot, 14); 79 addBSTreeNode(pRoot, 15); 80 addBSTreeNode(pRoot, 16); 81 inorderBSTree(pRoot); 82 return 0; 83 }
第五题: 判断整数序列是不是二元查找树的后序遍历结果
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
1 #include <iostream> 2 3 using namespace std; 4 5 bool checkIsOrNotAfterOrderBSTree(int *pc,int len) 6 { 7 bool left = true, right = true; 8 int i = 0,j = 0,root = pc[len-1]; //根肯定是最后一位 9 if(pc == NULL || len <= 0 ) 10 { 11 return false; 12 } 13 //找到根的左节点的结束位置 14 for(i = 0; i < len - 1; ++i) //注意这里的,len一定要减一,否则会与自身比较,陷入死循环 15 { 16 if(pc[i] > root) 17 break; 18 } 19 //剩下的都是右节点了,判断右节点是否都大于根节点 20 for(j = i; j < len - 1; ++j) 21 { 22 if(pc[j] < root) 23 { 24 return false; 25 } 26 } 27 if(i > 0) 28 left = checkIsOrNotAfterOrderBSTree(pc,i); 29 if(len - i > 1) 30 right= checkIsOrNotAfterOrderBSTree(&pc[i],len - i - 1); //减1是为了减掉根 31 return (left&&right); 32 } 33 int main() 34 { 35 int squene[] = {5,4,6,9,11,10,8}; 36 if(checkIsOrNotAfterOrderBSTree(squene,7)) 37 cout << "Yes" << endl; 38 else 39 cout << "No" << endl; 40 return 0; 41 }
这题是我参考http://blog.csdn.net/v_JULY_v/article/details/6126406,让我意识到:二叉树的问题一般都可以用递归来实现算法。