目录
0等概率随机洗牌:
转换大小写
2字符串复制
求3平方根和整数平方
辗转四法,寻求最大公约数
5两个整数交换
6二进制搜索
7反反复复的猴子吃桃子的问题
8输出每种基本数据类型的内存字节十六进制值
9查找数组长度
10单个循环查找数组中的最大值和第二个最大值
11回到哪一年的1月1日是星期几
12数字字符串与浮点数
使用13函数对象查找斐波那契数列:
确定14整数是否为2的整数平方
15如何更友好地停止控制台窗口
16舍入到特定标准,宏*p
17如何缩小解决方案空间,判断是否为小数。
18字统计
返回19个间隔的随机数
使用20枚举和共同体组合结构
使用21位域和共享体将double分成四部分显示。
22算术和位运算模拟比较运算符和条件语句
23模板递归继承
实施24 memmove()
定义25小时延迟函数
26合并排序
26快速排序
27堆排序
28跟山对齐
29自定义连接的列表迭代器
自定义30 string
31定制vector
32智能指针模拟
0等概率随机洗牌:
for(int I=n-1;I=0;I -)
Swap(arr[i],arr[rand(0,I)]);//rand(0,I)生成介于[0,i]之间的任意整数大小写转换
# include//位操作控制低5位(32)
# define UPPER(str)for(int I=0;str[I];)str[I]|=' A '-' A '
# define LOWER(str)for(int I=0;str[I];)str[I]=~(' A '-' A ');
Int main()
{
char str[]=' aBcDeF '
//UPPER(str);
Printf('%s\n 'str);
LOWER(str);
Printf('%s\n 'str);
}2字符串复制
# include
Char * strcpy (char * dst、constchar * src)
{
资产(dst!=空)(src!=NULL));
Char * start=dst
while(* dst=* src);
Return start
}
Int main()
{
char dst[]=' abcdefdd '
Char * src=' xydz
Printf('%s\n 'scpy(dst,src));
}求3平方根和整数平方
Doublesqrt (doublex,doublex0)//x是用于求平方根的数字,x0是平方根的估计值,可以是x/2
{
if(x=0)return 0;
双x 1=(x 0 x/x 0;
If(x1*x1-x 1e-5 || x1*x1-x -1e-5)
Return sqrt(x、x1) : //递归
Return x1
}
Double pow(double x,int n)
{
double ret=1;
While (n 0)
{//连接以下四个表达式进行思考
If (n%2==1) //n%2和n/2
ret=ret * x;//x,其中x 2重复
X=x * x
n=n/2;
}
Return ret
}4为寻找最大公约数而辗转。
Int gcd(int a、int b)
{
Return b?Gcd(b,A % B): A;
}
Int gcdLoop(int a、int b)
{
int r;
While(b0)
{
r=a % b;
a=b;
b=r;
}
return a;
}5两个整数交换
# include
Void swap(int *a、int *b)
{
*a
= *a + *b; *b = *a - *b; *a = *a - *b; } void swap2(int *a,int *b) { *a = *a * *b; *b = *a / *b; *a = *a / *b; } void swap3(int *a,int *b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } int main() { int a=3,b=4; printf("%d %d\n",a,b); swap(&a,&b); printf("%d %d\n",a,b); swap2(&a,&b); printf("%d %d\n",a,b); swap3(&a,&b); printf("%d %d\n",a,b); getchar(); }6 二分搜索
#include <;
int binsearch(int a[], int x, int low, int high)
{
int mid;
if(low > high)
return -1;
mid = (low + high) / 2;
if(x == a[mid])
return (mid);
else
if(x < a[mid])
binsearch(a, x, low, mid - 1);
else
binsearch(a, x, mid + 1, high);
}
int main()
{
int arr[] = {1,3,5,7,9,12,15,19};
int n = sizEOF arr / sizeof *arr;
int idx = binsearch(arr,9,0,n);
printf("%d\n",idx); // 4
getchar();
}
7 逆向迭代的猴子吃桃问题
int peachCount(int days) // 倒推
{
int peaches = 1; // 最后一天桃子数
while(days>1)
{
peaches = (peaches+1)*2; // 倒推递归
days--;
}
return peaches;
}
int peachCountRecursive(int day) // 递归
{
if(day == 1) // 最后一天,问题规模为1时
return 1;
else
return (peachCountRecursive(--day)+1)*2;
}
8 输出各基本数据类型的内存字节16进制值
c的指针可以将任意粒度的数据控制到字节。
void printIntBin(unsigned long n) // 输出unsigned的二进制位
{
bool r = (01&n);
if(n>=2)
printIntBin(n>>1); // 递归
putchar(r?'1':'0');
}
void showBytes(unsigned char* start, int len) // 输出len个start开始内存的16进制编码
{
for(int i=0;i<len;i++)
printf(" %.2x",start[i]);
printf("\n");
}
void showIntBytes(int x)
{
showBytes((unsigned char*)&x,sizeof(int));
}
void showDoubleBytes(double x)
{
showBytes((unsigned char*)&x,sizeof(double));
}
void showBytesByBig(unsigned char* start, int len) // 指定大端输出
{
unsigned int i = 0x00000001;
unsigned char* c = (unsigned char*)&i;
if(*c==1)// 小端返回true,大端返回0
{
for(int i=len-1;i>=0;i--)
printf(" %.2x",start[i]);
printf("\n");
}
}
9 求数组长度
long arr[] = {1,3,5,6,2,4,8};
int n = sizeof arr / sizeof *arr; // 少打几个字符,*arr即数组首元素
10 单循环找出数组中的最大值和次大值
#include <;
#define N 20
// 构造一个最小值,用做最大和次大的初始值
const int min = 1<<31; // -2147483648
int main()
{
int arr[N] = {0},i;
int max,second;
for(i=0;i<N;i++)
scanf("%d",&arr[i]);
max=second=min;
for(i=1;i<N;i++)
if(arr[i]>max) // 当找到了比最大更大的,前最大变成次大
{
second = max; // 前最大给到次大
max = arr[i]; // 当前最大给到max
}
else if(arr[i]>second && arr[i]!=max) // 比最大小,比次大大
second = arr[i];
printf("%d %d\n",max,second);
getchar();getchar();
return 0;
}
/* 将下面数据粘贴入
99 99 99 99 12
14 78 36 99 12
56 87 98 56 54
22 65 36 48 95
*/
11 返回某年的1月1号是星期几
// 公元1年1月1日是周一,365%7=1
int weekDay(int y) // 返回某年的1月1号是星期几
{ // 星期天返回0,星期1返回1
return (y + (y-1)/400 + (y-1)/4 - (y-1)/100)%7;
}
12 数字字符串转浮点数
double stringToDouble( char *p )
{
double intPart=0.0, fractionPart=0.0;
int multiplier = 1; /* change to -1 if string starts with minus */
/* Find the sign for the entire number */
if( *p == '+' ) p++;
if( *p == '-' )
{
multiplier = -1;
p++ ;
}
/* Convert the integer part of the number */
while( *p >= '0' && *p <= '9' )
{
intPart *= 10;
intPart += *p - '0';
p++ ;
}
/* Convert the fractional part of the number */
if( *p == '.' )
{
double divisor = 1.0;
p++ ;
while( *p >= '0' && *p <= '9' )
{
divisor *= 10.0;
fractionPart += (*p - '0')/divisor;
p++ ;
}
}
/* Put the pieces together */
return (intPart + fractionPart)*multiplier ;
}
13 用函数对象求斐波那契数列:
利用对象的状态。
#include <;
class Fib {
public:
Fib() : a0_(1), a1_(1) {}
int operator()() {
int temp = a0_;
a0_ = a1_;
a1_ = temp + a0_;
return temp;
}
private:
int a0_, a1_;
};
int main()
{
Fib fib;
for(int i=1;i<50;i++)
printf("%2d %d\n",i,fib());
getchar();
}
14 判断某一整数是否是2的整数次幂
bool is2pow(int m) // m的二进制位是否只有一个1
{
return (m & m-1) == 0;
}
15 如何较友好地停住控制台窗口
我们知道,在控制台输入时,scanf非字符时会忽略掉空白字符,输入字符时并不会忽略空白字符。所以有时一个简单的getchar()并不会停住控制台。
void PressEnterToContinue()
{
int c;
printf( "Press ENTER to continue... " );
fflush( stdout );
do c = getchar(); while((c != '\n') && (c != EOF));
}
16 以某一基准实现向上舍入,用宏实现*p++
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
va_arg(p,type) ( *(type *)((p += _INTSIZEOF(type)) - _INTSIZEOF(type)) )
上面第一个宏可以实现sizeof(int)的向上舍入,表示数据对齐;
上面第二个宏在模拟*p++,相当于*p; p++; 首先是整体表达式的值是+_INTSIZEOF(type)-_INTSIZEOF(type),没有影响到整体表达式的值,但p += _INTSIZEOF(type)对p产生了负作用,相当于指针的p++。
17 判断是否是素数
暴力枚举也是尽可能先缩减解空间。
int isPrime(int n)
{
if(n<2) return 0;
if(n==2) return 1;
if(n%2==0) return 0;
for(int i=3;i*i<=n;i+=2)
if(n%i == 0)
return 0;
return 1;
}
18 单词统计
int countWord(char *str)
{
bool wordInner = false;
int n = 0,i=0;
while(str[i]!='\0')
{
if(isspace(str[i]))
wordInner = false;
else if(wordInner==false && isalpha(str[i]))
{
n++;
wordInner = true;
}
else wordInner = true;
i++;
}
return n;
}
19 返回某区间的随机数
int randInt(int low,int high)
{
double quo = 1.0/(RAND_MAX+1.0);
return int(low+(rand()*quo)*(high-low+1));
}
20 使用枚举和共用体组合结构体
// 存货记录的声明
// 零件
typedef struct {
int cost;
int supplier;
// other information
}Partinfo;
// 装配件
typedef struct {
int n_parts;
struct SUBASSYPART{
char partno[10];
short quan;
}*part;
}Subassyinfo;
// 存货
typedef struct {
char partno[10] ;
int quan;
enum { PART, SUBASSY} type;
union{ // 存货不是零件就是装配件
Partinfo *part;
Subassyinfo *subassy;
}info;
}Invrec;
21 使用位域和共用体将double分成4部分显示:
#include <;
typedef struct packed_double {
unsigned int low32; // 小数位 低32位
unsigned int low20:20; // 小数位 低33-52位
unsigned int exp11:11; // 指数位 低53-63位,移码1023+二进制整数位-1
unsigned int sign:1; // 符号位
} packed_double;
typedef union {
double d;
packed_double b;
} packed;
int main()
{
packed pd;
= -15.75;
= 12.3;
printf("%u %u %u %u\n",);
getchar();
return 0;
}
/*
0 1026 1015808 0
*/
22 算术运算和位运算模拟比较运算符和条件语句
void compareEx(int a,int b) // 算术运算和位运算模拟比较运算符和条件语句
{
int t = (a-b)>>(sizeof(int)*8-1); // 取首位
if(t == -1)
cout<<"a<b\n"<<endl;
if(a-b == 0)
cout<<"a==b\n"<<endl;
if(a-b != 0 && t == 0)
cout<<"a>b\n"<<endl;
}
23 模板递归求阶乘
模板可以被递归调用,在模板递归的过程中,可以执行两种编译期计算:数值计算和类型计算。
#include <iostream>
template<unsigned int n>struct Factorial{
enum {
value = n * factorial<n - 1>::value
};
};
template<>struct factorial<0>{ // 模板特化终止递归
enum { value = 1 };
};
int main()
{
std::cout << factorial<7>::value << std::endl; // prints "5040"
}
在主模板template<unsigned int n>struct factoria的定义中,使用了模板自身struct factorial<N-1>::value。编译器会一直用不同的N-1的值来具现化主模板,一直到N变为1,这时选择Factorial的特化版本template<> struct Factorial<0>,内部的value变为1,递归终止。
24 memmove()实现
#include <;
void * my_memmove(void * dst,const void * src,int count)// 从src开始移动count个字节到dst
{
void * ret = dst;
if(dst <= src || ((char *)src + count) <= (char *)dst) // dst在前或src在前但内存区域不重叠
{
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else // (src<dst && (char *)dst < ((char *)src + count)) // src在前且内存区域有重叠
{ // 也就是dst重载了src的后面部分时
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
int main()
{
char src[] = "abcdefghi";
puts((char*)my_memmove(src+3,src,5));// abcdei
puts(src); // abcabcdei
getchar();
}
25 定义时间延迟函数
#include <iostream>
#include <;
//定义时间延迟函数
void Dtime(double dt) {
time_t current_time;
time_t start_time;
time(&start_time); // 得到开始时间
do{ // 延迟处理
time(¤t_time);
}while (difftime(current_time,start_time)<dt);
}
void displayTime(int n)
{
int i;
time_t current_time;
char *timep;
for(i=0;i<n;i++) {
time(¤t_time);
timep=ctime(¤t_time);
system("cls");
//cputs(timep);
printf("%s\n",timep);
Dtime(1);
}
}
int main()
{
displayTime(10);
}
26 快速排序
void quickSort(int arr[],int size,int low,int high)
{
int i,j,t;
if(low<high)
{
i=low;
j=high;
t=arr[low];
while(i<j)
{
while(i<j && arr[j]>t)
j--;
if(i<j)
{
arr[i] = arr[j];
i++;
}
while(i<j && arr[i]<=t)
i++;
if(i<j)
{
arr[j] = arr[i];
j--;
}
}
arr[i] = t;
quickSort(arr,size,low,i-1);
quickSort(arr,size,i+1,high);
}
}
26 归并排序
void Merge(int A[], int left, int mid, int right)
{
int len = right - left + 1;
int *temp = new int[len]; // 辅助空间O(n)
int index = 0;
int i = left; // 前一数组的起始元素
int j = mid + 1; // 后一数组的起始元素
while(i <= mid && j <= right) // 从小到大依次放到辅助数组中
if(A[i] <= A[j])
temp[index++] = A[i++];
else
temp[index++] = A[j++];
while(i <= mid) // 对子序列A[left:mid]剩余的依次处理
temp[index++] = A[i++];
while(j <= right) // 对子序列B[mid+1:right]剩余的依次处理
temp[index++] = A[j++];
for(int k = 0; k < len; k++) // 将合并后的序列复制到原来的A数组
A[left++] = temp[k];
}
// 递归实现的归并排序(自顶向下)
void MergeSortRecursion(int A[], int left, int right)
{
if(left == right) // 当待排序的序列长度为1时,递归开始回溯,进行merge操作
return;
int mid =(left + right) / 2;
MergeSortRecursion(A, left, mid); // 参数迭代:right = mid
MergeSortRecursion(A, mid + 1, right); // 参数迭代:left = mid+1
Merge(A, left, mid, right); // 递归返回时执行部分
Merge(A, left, mid, right);
}
// 非递归(迭代)实现的归并排序(自底向上)
void MergeSortIteration(int A[], int len)
{
int left, mid, right;// 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right]
for(int i=1; i<len; i*=2) // 子数组的大小i初始为1,每轮翻倍
{
left = 0;
while(left + i < len) // 后一个子数组存在(需要归并)
{
mid = left + i - 1;
right = (mid+i)<len?mid+i:len-1;// 后一个子数组大小可能不够
Merge(A, left, mid, right);
left = right + 1; // 前一个子数组索引向后移动
}
}
}
27 堆排序
void Swap(int A[], int i, int j)
{
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
void Heapify(int A[], int i, int size) // 从A[i]向下进行堆调整
{
int left_child = 2 * i + 1; // 左孩子索引
int right_child = 2 * i + 2; // 右孩子索引
int max = i; // 选出当前结点与其左右孩子三者之中的最大值
if (left_child < size && A[left_child] > A[max])
max = left_child;
if (right_child < size && A[right_child] > A[max])
max = right_child;
if (max != i)
{
Swap(A, i, max); // 把当前结点和它的最大(直接)子节点进行交换
Heapify(A, max, size);
// 递归调用,继续从当前结点向下进行堆调整
}
}
int BuildHeap(int A[], int n) // 建堆,时间复杂度O(n)
{
int heap_size = n;
for (int i = heap_size / 2 - 1; i >= 0; i--) // 从每一个非叶结点开始向下进行堆调整
Heapify(A, i, heap_size);
return heap_size;
}
void HeapSort(int A[], int n)
{
int heap_size = BuildHeap(A, n); // 建立一个最大堆
while (heap_size > 1)
{ // 堆(无序区)元素个数大于1,未完成排序
// 将堆顶元素与堆的最后一个元素互换,并从堆中去掉最后一个元素
// 此处交换操作很有可能把后面元素的稳定性打乱,
// 所以堆排序是不稳定的排序算法
Swap(A, 0, --heap_size);
Heapify(A, 0, heap_size); // 从新的堆顶元素开始向下进行堆调整,时间复杂度O(logn)
}
}
28 希尔排序
void output(int a[], int n){ //输出数组元素
for(int i = 0; i<n;++i)
printf("%2d ",a[i]);
printf("\n");
}
void ShellSort(int A[], int n)
{
int h = 0;
while (h <= n) // 生成初始增量
h = 3 * h + 1;
while (h >= 1)
{
for (int i = h; i < n; i++)
{
int j = i - h;
int get = A[i];
while (j >= 0 && A[j] > get)
{
A[j + h] = A[j];
j = j - h;
}
A[j + h] = get;
printf("gap%2d:\n",h);
output(A,n);
}
h = (h - 1) / 3; // 递减增量
}
}
29 链表迭代器自定义
// 链表迭代器自定义
//#include <list>
#include <iostream>
#include <string>
using namespace std;
//1.数据组成
template <typename T>
struct singleList
{
singleList<T>* next;
T data;
singleList() // 创建表头
{
this->next = NULL;
}
singleList(T data) // 创建节点
{
this->data = data;
this->next = NULL;
}
// 创建节点+连接节点的功能
singleList(T data, singleList<T>* next)
{
this->data = data;
this->next = next;
}
};
template <typename T>
class list{
public:
list() // 构造函数作用:构造对象
{ // 初始化基本数据成员,描述最初状态
sizeList = 0;
listHeadNode = listTailNode = NULL;
}
void push_back(T data) // 基本行为:插入操作
{
singleList<T>* newNode = new singleList<T>(data);
if (listHeadNode == NULL)
listHeadNode = newNode;
else
listTailNode->next = newNode;
listTailNode = newNode;
//listTailNode->next=NULL;
}
void push_front(T data)
{
singleList<T>* newNode = new singleList<T>(data);
if (listHeadNode == NULL)
listTailNode = newNode;
else
newNode->next = listHeadNode;
listHeadNode = newNode;
}
void printList() //测试行为:遍历结构(打印输出)
{
singleList<T>* pMove = listHeadNode;
while (pMove)
{
cout << pMove->data << " ";
pMove = pMove->next;
}
cout << endl;
}
singleList<T>* begin()
{
return listHeadNode;
}
singleList<T>* end()
{
return listTailNode->next; // 表示链表最后那个位置,NULL的位置
}
int size() const // 万金油行为
{
return sizeList;
}
bool empty() const
{
return sizeList == 0;
}
public:
class iterator
{
public:
void operator=(singleList<T>* pMove) // 实现begin对iterator对象的初始化
{ // 实质初始化对象中的属性
this->pMove = pMove;
}
singleList<T>* getData()
{
return pMove;
}
bool operator!=(singleList<T>* pMove)
{
return this->pMove != pMove;
}
iterator& operator++(int) //i=i+1; //实质是链表的一个移动指针走到一下一个节点
{
this->pMove = this->pMove->next;
return (*this);
}
T operator*()
{
return this->pMove->data;
}
protected:
singleList<T>* pMove; // 迭代器就是对容器元素指针的封装
};
protected: // 抽象数据成员
// 遵循的原则:抽象出来的属性能够便于描述行为(成员函数)
singleList<T>* listHeadNode;
singleList<T>* listTailNode;
int sizeList; // 万金油属性
};
int main()
{
list<string> mylist;
myli("I");
myli("Love");
myli("you");
();
list<string>::iterator myIter;
//myIter=myli();
//cout<<myI()->data<<endl;
for (myIter = myli(); myIter != myli(); myIter++)
{
cout << *myIter << " ";
}
cout << endl;
return 0;
}
30 string自定义
#include <;
#include <;
class String
{
public:
String(const char* cstr = 0);
String(const String& str);
String& operator=(const String& str);
~String(){
delete[] m_data;
}
char* get_c_str() const{
return m_data;
}
private: char* m_data;
};
String::String(const char* cstr)
{
if(cstr)
{
m_data = new char[strlen(cstr)+1];
strcpy(m_data,cstr);
}
else {
m_data = new char[1];
*m_data = '\0';
}
}
String::String(const String& str)
{
m_data = new char[strlen)+1];
strcpy(m_data,);
}
String& String::operator=(const String& str)
{
if(this == &str)
return *this;
delete[] m_data;
m_data = new char[strlen)+1];
strcpy(m_data,);
return *this;
}
int main()
{
String str("abc");
String str2(str);
String str3 = str2;
printf("%s\n",());
return 0;
}
31 自定义vector
#include<iostream>
using namespace std;
class Vector {
public:
Vector(int s);
int size();
double& operator[](int i);
private:
double* elem; // pointer to the elements
int sz; // the number of elements
};
Vector::Vector(int s) // construct a Vector
{
sz = s;
elem = new double[s];
}
double& Vector::operator[](int i) // element access: subscripting
{
return elem[i];
}
int Vector::size()
{
return sz;
}
double read_and_sum(int n)
{
Vector v(n); // make a vector of s elements
for (int i=0; i!=v.size(); ++i)
cin>>v[i]; //read into elements
double sum = 0;
for (i=0; i!=v.size(); ++i)
sum+=v[i]; //take the sum of the elements
return sum;
}
void main()
{
cout<< read_and_sum(6)<<endl;
system("pause");
}
/*
1 2 3 4.4 5 6.6
22
*/
32 智能指针模拟
#include<iostream>
#include<stdexcept>
using namespace std;
#define TEST_SMARTPTR
class Stub // stub code是占坑的代码,桩代码给出的实现是临时性的/待编辑的。
{
public:
void print(){
cout<<"Stub:print"<<endl;
}
~Stub(){
cout<<"Stub:Destructor"<<endl;
}
};
template<typename T>
class SmartPtr
{
T* ptr;
size_t* pUse;
public:
SmartPtr(T *p=0):ptr(p),pUse(new size_t(1)){}
SmartPtr(const SmartPtr&src):ptr),pUse){
++*pUse;
}
SmartPtr&operator=(const SmartPtr&rhs){
//self-assigning is also right
++*r;
decrUse();
ptr=r;
pUse=r;
return *this;
}
T* operator->(){
if(ptr)
return ptr;
throw std::runtime_error("access through NULL pointer");
}
const T* operator->()const{
if(ptr)
return ptr;
throw std::runtime_error("access through NULL pointer");
}
T &operator*(){
if(ptr)
return *ptr;
throw std::runtime_error("dereference of NULL pointer");
}
const T &operator*()const{
if(ptr)
return *ptr;
throw std::runtime_error("dereference of NULL pointer");
}
~SmartPtr(){
decrUse();
#ifdef TEST_SMARTPTR
std::cout<<"SmartPtr:Destructor"<<std::endl;//fortesting
#endif
}
private:
void decrUse(){
if(--*pUse==0){
delete ptr;
delete pUse;
}
}
};
int main()
{{
try{
SmartPtr<Stub>t;
t->print();
}catch(const exception&err){
cout<<err.what()<<endl;
}
SmartPtr<Stub>t1(new Stub);
SmartPtr<Stub>t2(t1);
SmartPtr<Stub>t3(new Stub);
t3=t2;
t1->print();
(*t3).print();
}//增加一个块结构,为了看到对象离开作用域后的析构结果
system("pause");
return 0;
}
/*output:
SmartPtr:Destructor
access through NULL pointer
Stub:Destructor
Stub:print
Stub:print
//以下是离开作用域后的析构
SmartPtr:Destructor
SmartPtr:Destructor
Stub:Destructor
SmartPtr:Destructor
*/
-End-