C/C++ 经典算法实例
二分查找的代码
int bfind(int* a,int len, int val) { int le = 0,re = len - 1,m; while (le<=re) { m = (le+re)/2; if(a[m] == val) return m; if(a[m]>val) re = m - 1; else le = m + 1; } return -1; // }
写出在母串中查找子串出现次数
int count1(char* str,char* s) { char* s1; char* s2; int count = 0; while(*str!='\0') { s1 = str; s2 = s; while(*s2 == *s1&&(*s2!='\0')&&(*s1!='\0')) { s2++; s1++; } if(*s2 == '\0') count++; str++; } return count; }
查找第一个匹配子串位置,如果返回的是s1长度len1表示没有找到
size_t find(char* s1,char* s2) { size_t i=0; size_t len1 = strlen(s1); size_t len2 = strlen(s2); if(len1-len2<0) return len1; for(;i<len1-len2;i++) { size_t m = i; for(size_t j=0;j<len2;j++) { if(s1[m]!=s2[j]) break; m++; } if(j==len) break; } return i<len1-len2?i:len1; }
实现strcpy函数
char *strcpy(char *destination, const char *source) { assert(destination!=NULL&&source!=NULL); char* target = destinaton; while(*destinaton++=*source++); return target ; }
实现strcmp函数
int strcmp11(char* l,char* r) { assert(l!=0&&r!=0); while(*l == *r &&*l != '\0') l++,r++; if(*l > *r) return 1; else if(*l == *r) return 0; return -1; }
实现字符串翻转
void reserve(char* str) { assert(str != NULL); char * p1 = str; char * p2 = str-1; while(*++p2); //一般要求不能使用strlen p2 -= 1; while(p1<p2) { char c = *p1; *p1++ = *p2; *p2-- = c; } }
将一个数字字符串转换为数字."1234" -->1234
int atoii(char* s) { assert(s!=NULL); int num = 0; int temp; while(*s>='0' && *s<='9') { num *= 10; num += *s-'0'; s++; } return num; }
将一个单链表逆序
struct list_node
{
list_node(int a,list_node* b):data(a),next(b) //这个为了测试方便
{}
int data;
list_node* next;
};
void reserve(list_node* phead)
{
list_node* p = phead->next;
if(p == NULL || p->next == NULL) return; //只有头节点或一个节点
list_node* p1=p->next;
p->next=NULL;
while(p1!=NULL)
{
p = p1->next;
p1->next = phead->next;
phead->next = p1;
p1 = p;
}
}
循环链表的节点对换和删除。
//双向循环
list_node* earse(list_node* node)
{
// if(node == rear) return node->next; //对于头节点可判断也可不判断。最好加上
list_node* next = node->next;
next->prev = node->prev;
node->prev->next = next;
delete node;
retrun next;
}
//单项循环
list_node* earse(list_node* node)
{
// if(node == rear) return node->next; //对于头节点可判断也可不判断。最好加上
list_node* p = rear;
while(p->next != node) p=p->next;
p->next = node->next;
delete node;
retrun p->next;
}
.实现任意长度的整数相加或者相乘功能。
void bigadd(char* num,char* str,int len)
{
for(int i=len;i>0;i--)
{
num += str;
int j = i;
while(num[j]>=10)
{
num[j--] -= 10;
num[j] += 1;
}
}
}
.写函数完成内存的拷贝
void* memcpy( void *dst, const void *src, unsigned int len )
{
register char *d;
register char *s;
if (len == 0)
return dst;
if ( dst > src ) //考虑覆盖情况
{
d = (char *)dst + len - 1;
s = (char *)src + len - 1;
while ( len >= 4 ) //循环展开,提高执行效率
{
*d-- = *s--;
*d-- = *s--;
*d-- = *s--;
*d-- = *s--;
len -= 4;
}
while ( len-- )
{
*d-- = *s--;
}
}
else if ( dst < src )
{
d = (char *)dst;
s = (char *)src;
while ( len >= 4 )
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
len -= 4;
}
while ( len-- )
{
*d++ = *s++;
}
}
return dst;
}
出现次数相当频繁
编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
解答:
//普通构造函数
String::String(const char *str)
{
if(str==NULL)
{
m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的空
//加分点:对m_data加NULL 判断
*m_data = '\0';
}
else
{
int length = strlen(str);
m_data = new char[length+1]; // 若能加 NULL 判断则更好
strcpy(m_data, str);
}
}
// String的析构函数
String::~String(void)
{
delete [] m_data; // 或delete
m_data;
}
//拷贝构造函数
String::String(const String &other) // 得分点:输入参数为const型
{
int length = strlen(other.m_data);
m_data = new char[length+1]; //加分点:对m_data加NULL 判断
strcpy(m_data, other.m_data);
}
//赋值函数
String & String::operate =(const String &other) // 得分点:输入参数为const型
{
if(this == &other)
//得分点:检查自赋值
return *this;
delete [] m_data; //得分点:释放原有的内存资源
int length = strlen( other.m_data );
m_data = new char[length+1]; //加分点:对m_data加NULL 判断
strcpy( m_data, other.m_data );
return *this; //得分点:返回本对象的引用
}
剖析:
能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!
在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。
实现strcpy
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ );
return address;
}
编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh”
函数头是这样的:
//pStr是指向以'\0'结尾的字符串的指针
//steps是要求移动的n
void LoopMove ( char * pStr, int steps )
{
//请填充...
}
解答:
正确解答1:
void LoopMove ( char *pStr, int steps )
{
int n = strlen( pStr ) - steps;
char tmp[MAX_LEN];
strcpy ( tmp, pStr + n );
strcpy ( tmp + steps, pStr);
*( tmp + strlen ( pStr ) ) = '\0';
strcpy( pStr, tmp );
}
正确解答2:
void LoopMove ( char *pStr, int steps )
{
int n = strlen( pStr ) - steps;
char tmp[MAX_LEN];
memcpy( tmp, pStr + n, steps );
memcpy(pStr + steps, pStr, n );
memcpy(pStr, tmp, steps );
}