代码,非剑指offer 1

1.模拟实现  strstr

char* MyStrstr( const char* str1, const char* str2 ){    
   assert( NULL != str1 && NULL != str2 );  
     
   while ('\0' != *str1){    
       const char* p1 = str1;  
       const char* p2 = str2;  
         
       while (('\0' != *p1) && ('\0' != *p2) && (*p1 == *p2)){  
           ++p1;  
           ++p2;  
       }  
         
       if ('\0' == *p2)  
           return str1;    
         
       ++str1;  
   }  
     
   return NULL;    
}

2.模拟实现 strcpy

char* MyStrcpy(char* dest, const char* src){    
   assert( NULL != dest && NULL != src );  
     
   char* pAddress = dest;  
   while ('\0' != (*dest++ = *src++))  
       ;  
 
   return pAddress;  
}

3.编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:

class String{   
public:   
   String( const char* str = NULL );           // 普通构造函数   
   String(const String &other);                // 拷贝构造函数   
   ~ String(void);                             // 析构函数   
   String & operator =(const String &other);   // 赋值函数   
 
private:   
   char *m_data;                               // 用于保存字符串   
};
String::String( const char* str ){  
   if (NULL==str){  
       m_data = new char[1];           // 对空字符串自动申请存放结束标志'\0'的空间  
       *m_data = '\0';   
   }  
   else{  
       int length = strlen(str);   
       m_data = new char[length+1];  
         
       strcpy(m_data, str);   
   }  
}  
 
// String的析构函数  
String::~String( void ){  
   delete [] m_data;                   // 或delete m_data;  
}  
 
// 拷贝构造函数  
// 输入参数为const型   
String::String( const String& other ){  
   int length = strlen( other.m_data );   
   m_data = new char[length+1];   
     
   strcpy( m_data, other.m_data );   
}  
 
// 赋值函数  
// 输入参数为const型  
MyString& MyString::operator=( const MyString& str ){  
   // 检查自赋值  
   if ( &str != this ){  
       MyString strTemp( str );  
 
       char* pTemp = strTemp.m_pData;  
       strTemp.m_pData = m_pData;  
       m_pData = pTemp;  
   }  
 
   // 返回本对象的引用  
   return *this;  
}

当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数

如果出函数作用域后还存在则可以返回引用, 不存在则不能返回引用,要返回临时对象


4.宏函数  -->  交换两个数

#define SWAP( a, b )        \  
do {                        \  
   (a) = ((a)^(b));        \  
   (b) = ((a)^(b));        \  
   (a) = ((a)^(b));        \  
}while (0)

5.模拟实现 strncpy

char* MyStrncpy( char* dest, const char* src, size_t len ){    
   assert( NULL != dest && NULL != src );  
 
   char* ret = dest;    
   while (0 != len--){  
       if (0 != (*dest = *src)){  
           ++dest;    
           ++src;  
       }  
   }  
     
   if (len > 0)    
       while (len--)    
           *dest++ = '\0';   
 
   return ret;    
}

在安全性方面,显然strncpy要比strcpy安全得多,strcpy无法控制拷贝的长度,不小心就会出现dest的大小无法容纳src的情况,就会出现越界的问题,程序就会崩溃。而strncpy就控制了拷贝的字符数避免了这类问题,但是要注意的是dest依然要注意要有足够的空间存放src,而且src 和 dest 所指的内存区域不能重叠


6.获取一个数二进制序列的奇数位和偶数位

int a[32];  
for (int i = 0; i < 32; ++i){  
   a[i] = data % 2;  
   data /= 2;  
}  
 
// 偶数  
for (int i = 1; i <= 31; i += 2)  
   cout << arr[i];  
 
// 奇数  
for (int i = 0; i <= 20; i += 2)  
   cout << arr[i];

7.请写一个模板类,来求两个数中的最大值

注意:求两个"数"的最大值,若两个"数"不是内置类型,而是自定义类型比较大小。则1.看原自定义类型是否重载operator <( )运算符 2.仿函数

template <typename T>  
class MaxNumber{  
public:  
   MaxNumber( )  
       : _a( a )  
       , _b( b )  
   {}  
 
   T Max( ){  
       return _a > _b ? _a : _b;  
   }  
 
private:  
   T _a;  
   T _b;  
};  
 
int main( ){  
   int a;  
   int b;  
   cin >> a >> b;  
 
   MaxNumber<int> m( a, b );  
   m.Max( );  
 
   return 0;  
}

8.写一个函数来判断一个字符串是否是对称的 

bool Fun( const char* str ){  
   bool ret = true;  
     
   if (NULL == str || ('\0' == *str))  
       return ret;  
 
   char* pBegin = str;  
   char* pEnd = str + strlen(str) - 1;  
 
   // 注意此处不能用 pBegin != pEnd 判断. 想想字符串为偶数个字符的情形(不包括'\0'),是否两个指针刚好错过了.  
   while (pBegin < pEnd){  
       if (*pBegin == *pEnd){  
           ++pBegin;  
           --pEnd;  
       }  
       else{  
           ret = false;  
           break;  
       }  
   }  
 
   return ret;  
}

9.二分查找的算法

int BinarySearch( int* arr, int len, int key ){  
   assert( NULL != arr && len > 0 );  
 
   int left = 0;    
   int right = len - 1;    
   int mid = 0;  
 
   while (left<=right){    
       mid = left + ( (right-left)>>1 );// 不直接用 (left+right)/2 是 防止越界 和 提高效率    
 
       if (arr[mid] < key)    
           left = mid + 1;    
       else if (arr[mid] > key)    
           right = mid - 1;    
       else     
           return mid;  
   }  
 
   return -1;    
}

right = n - 1  =>  while (left <= right) (利用只有一个元素时情景去想, 如果是 left(0) < rightr(1 - 1 == 0) 循环根本进不去。 所以是<=)  =>  right = middle - 1(middle索引的元素已经被判断,又因为是 left <= right, 所以 right = mid - 1 如果是 right = mid, 这mid索引这个位置元素又会在下次循环被遍历一次);  


right = n  =>  while (left < right)(数组只有一个元素  0 < 1  -->  循环进去一次,<=循环进去两次)  =>  right = middle(middle已经被遍历, 又因为left < right, 若right = middle - 1则middle - 1那个元素被略过, 而right = middle -> left < right --> middle不会被重复遍历,middle - 1的元素也不会被略过);  
middle = ((left+right) >> 1);  这样的话 left 与 right 的值比较大的时候,其和可能溢出。  -->  middle = left + ( (right - left) >> 1 )



10.快速排序

template <typename T>  
void QuickSort( vector<T>& a ){  
   QuickSort( a, 0, a.size( )-1 );  
}  
 
template <typename T>  
const T& Median3( vector<T>&a, int left, int right ){  
   int center = left + ((right - left) >> 1);  
 
   if (a[center] < a[left])  
       swap( a[left], a[center] );  
   if (a[right] < a[left])  
       swap( a[left], a[right] );  
   if (a[right] < a[center])  
       swap( a[center], a[right] );  
 
   swap( a[center], a[right - 1] );  
   return a[right - 1];  
}  
 
template <typename T>  
void QuickSort( vector<T>& a, int left, int right ){  
   if (left + 10 <= right){  
       T pivot = median3( a, left, right );  
 
       int i = left;  
       int j = right - 1;  
       for ( ; ; ){  
           while (a[++i] < pivot)  
               ;  
 
           while (a[--j] > pivot)  
               ;  
 
           if ( i < j )  
               swap( a[i], a[j] );  
           else  
               break;  
       }  
 
       swap( a[i], a[right-1] );  
 
       QuickSort( a, left, i - 1 );  
       QuickSort( a, i + 1, right );  
   }  
   else  
       InsertSort( a, left, right );  
}

11.插入排序

插入排序由N-1趟排序组成。对于p=1到N-1趟,插入排序保证从位置0到位置p上的元素为已排序状态。事实:位置0到位置p-1上的元素是已经排过序的。

在第p趟,我们将位置p上的元素向左移动至它在前p+1个元素中的正确位置上。

template <typename T>  
void InsertSort( vector<T>& a ){  
   int j;  
 
   for (int p = 1; p < a.size( ); ++p){  
       T tmp = a[p];  
       for (j = p; j > 0 && tmp < a[j-1]; ++j)  
           a[j] = a[j-1];  
 
       a[j] = tmp;  
   }  
}

12.冒泡、选择

void BubbleSort( void ){    
   int i = 0;    
   int j = 0;    
   
   for (i = 0; i < n - 1; ++i){    
       for ( j = 0; j < n - i - 1; ++j ){    
               /*      */    
           }  
   }    
}    
 
void SelectSort( void ){    
   int maxIndex = 0;    
   int i = 0;    
   int j = 0;    
   
   for (i = 0; i < n - 1; ++i)  {    
       maxIndex = i;    
   
       for ( j = i; j < n - 1; ++j )// j 从 i 开始;下来依次为 j < n - 1; arr[j + 1];//j 从 i + 1 开始,则依次为 j < n; arr[j]  
       {    
           if ( arr[j + 1] > arr[maxIndex] )    
               maxIndex = j + 1;  
       }    
   
       swap ( arr[i], arr[maxIndex] );    
   }    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值