每天一题C++

一、循环队列

关键掌握点:

  • 1、定义一个循环队列中有前标志front和后标志rear
  • 2、判断队列是否满–后标志位加1后追上前标志位:(rear + 1) % MAXLEN 是否等于 front
  • 3、判断队列是否为空: rear 是否等于 front
  • 4、当前循环队列中已有的元素个数:(rear - front + MAXLEN ) % MAXLEN
  • 5、注意哦构成循环队列的数组如果大小为n那么循环队列满的情况就是有n-1个元素的时候了
//声明一个循环队列的类 
class CQueue
{
	private:
		int *array;
		unsigned int len;
		int front;
		int rear;
	public:
		CQueue(unsigned int len);
		CQueue(CQueue &que);
		~CQueue();
		
		unsigned int GetTotaLen();
		unsigned int GetCurLen();
		unsigned int GetRemainLen(); 
		int Push(int val);
		int Pop();
		bool IsEmpty();
		bool IsFull();
}; 

//循环队列的构造函数,生成可以存储len个长度的队列 
CQueue:: CQueue(unsigned int len)
{
	this->array = new int[len + 1];//n个元素的数组存n-1个数据就算是满了 
	this->len = len + 1;
	memset(this->array, 0, len + 1);
	this->front = 0;
	this->rear = 0;
}

//循环队列的拷贝构造函数 
CQueue:: CQueue(CQueue &que)
{
	int i = 0;
	unsigned int len = que.GetTotaLen();
	this->array = new int[len];
	this->len = len;
    this->front = 0;
    this->rear = 0;
	while (!que.IsEmpty())
	{
		this->array[i++] = que.Pop();
		this->rear++;
	}	
}

//析构函数 
CQueue:: ~CQueue()
{
	delete[] this->array;
}

//获取循环队列能存储的元素个数 
inline unsigned int CQueue:: GetTotaLen()
{
	return this->len - 1; 
}

//获取循环队列当前已用的存储空间
inline unsigned int CQueue:: GetCurLen()
{
	return (this->rear - this->front + this->len) % this->len;
}

//队列还能存多少个元素 
inline unsigned int CQueue:: GetRemainLen()
{
	
	return  (this->len - 1) - (this->rear - this->front + this->len) % this->len;
}

//入队列 
int CQueue:: Push(int val)
{
	if (this->IsFull())
	{
		return -1;
	}
	else
	{
		this->array[this->rear] = val;
		this->rear = (this->rear + 1) % this->len;
		return 0;
	}
}

//出队列 
int CQueue:: Pop()
{
	int val;
	if (this->IsEmpty())
	{
		return -1;//这个返回-1感觉也不合适,应为队列中也有可能是存了-1
	}
	else
	{
		val = this->array[this->front];
		this->front = (this->front + 1) % this->len;
		return val;
	}
}

//判断队列是否是空 
bool CQueue::IsEmpty() 
{
	return (this->front == this->rear ? true:false);
}

//判断是否是满队列了 
bool CQueue::IsFull() 
{
	return ((this->rear + 1 ) % this->len == this->front ? true:false);
}

二、生成0-100的随机数,并用二分法查找其中的某个值

解题的步奏:

  • 1、写一个函数可以生成0-100的随机数且不重复:
  • (1)生成一个元素0-100的数组temp
  • (2)随机从temp中取出一个数放入数组a中,如此反复直到temp中的元素取完即可在a中生成0-100的随机数且不重复
//调整数组a,去掉索引为midIndex的元素,并返回数组a的新的startIndex和endIndex的值 
void ResizeArray(int *a, int &startIndex, int &endIndex, int midIndex)
{
	int leftSpace = midIndex - startIndex;
	int rightSpace = endIndex - midIndex;
	bool IsLeft = leftSpace  < rightSpace ? true:false;
	//为了减少移动元素的操作, 判断是从midIndex 的左边移动还是右边移动(左右间距决定) 
	if (IsLeft)
	{
		//左边的元素往右移(1 2 3 [mid] 4 5 6 7 8) -> ([1] 1 2 3 4 5 6 7 8)
	    //移动后改变startIndex 加1 
		while (startIndex != midIndex)
		{
			a[midIndex] = a[midIndex - 1];
			midIndex--;
		}
		startIndex++;
	} 
	else
	{
		//右边的元素往左移动 (1 2 3 [mid] 4 5) -> (1 2 3 4 5 [5])
		//移动后改变endIndex 减一 
		while (endIndex != midIndex)
		{
			a[midIndex] = a[midIndex + 1];
			midIndex++;
		}
		endIndex--;
	}
	return;
}

//获取从startNum到endNum的不重复的随机数并存入数组a中 
void GetRandNum(int *a, int startNum, int endNum)
{
	int len = endNum - startNum + 1;
	int *temp = new int[len]; //申请一个临时的数组temp 
	int index = 0;
	int i = startNum;
	int j = 0;
	int aIndex = 0;//as数组的索引记录 
	int tempStartIndex = 0;	//临时数组temp的当前的开始索引 
	int tempEndIndex = len - 1;//临时数组temp的当前的结束索引 

	for (; i <= endNum; i++)
	{
		temp[j++] = i;
	}

	srand(time(NULL));//要产生真正的随机数,这个随机数种子必须设置 
	for (i = startNum; i <= endNum; i++, j--)
	{

	
		index = rand() % j;//随机产生一个index 在0 到 j-1 范围内的 
		a[aIndex++] = temp[index + tempStartIndex];//根据随机的index在 数组固定的范围中temp中随机取 出一个数 
		ResizeArray(temp, tempStartIndex, tempEndIndex, index + tempStartIndex);//已经取出了一个数,需重新调整数组temp的开始索引和结束索引 
	}
	
	delete[] temp;//释放申请的内存 
	return;
}

2、使用排序算法先对生成的数组a排序
3、对排序后的a数组使用二分法求具体某一个数在数组中的索引
(1)递归方法实现的二分查找法

	//二分查找法,递归的方式,(开始索引,结束索引,要查找的值)
int BinarySearch(int a[], int startIndex, int endIndex, int val)
{
	int midIndex = (startIndex + endIndex) / 2;
	if (a[midIndex] == val)//找到了返回 
	{
		return midIndex;
	}
	else if (a[midIndex] < val)//找右边的 
	{
		if (midIndex + 1 > endIndex)//右边没有元素了还找不到,就是没有了 
		{
			return -1;
		}
		startIndex = midIndex + 1;
	}
	else                        //找左边的 
	{
		if (midIndex - 1 < startIndex)//左边没有元素了还找不到,就是没有了 
		{
			return -1;
		}
		endIndex = midIndex - 1;
	}
	
	return BinarySearch(a, startIndex, endIndex, val);
}
(2)循环方法实现的二分法
//二分查找法,使用循环的方式,找到的索引值在index中返回 
bool BinarySearch1(int a[], int len, int val, int *index)
{
	int startIndex = 0;
	int endIndex = len - 1;
	int midIndex;
	while (endIndex >= startIndex)
	{
		midIndex = (startIndex + endIndex) / 2;
		if (a[midIndex] == val) //找到了返回 
		{
			*index = midIndex;
			return true;
		}
		else if(a[midIndex] < val) //找右边的 
		{
			if (midIndex + 1 > endIndex) //右边都没有元素了还找不到,那就是没有咯 
			{
				return false;
			}
			startIndex = midIndex + 1;
		}
		else                      //找左边的 
		{
			if (startIndex > midIndex - 1)//左边都没有元素了还是找不到,那就是没有咯 
			{
				return false;
			}
			endIndex = midIndex - 1;
		}	
	}
	
	return false; 
}
三、给你一个浮点数1000.1234,你会输出“壹零零零点壹贰弎肆

考虑一下如何把一个浮点数转换为字符串存储起来

//浮点数转换为字符串,该程序有问题 
//如果把程序中的float转换成double又是另外一种结果
void Flt2Str(char *a, float f)
{
	int hight; //取出float的整数部分 
	float low; //取出float的小数部分 
	char *tempA = a;//临时指针指向a 
	int count = 0;
	float tempF = f >= EPS ? f:-f;//我们只考虑正数的情况,这里把负数转换为正数 
	hight = (int)tempF; 
	tempF = tempF - hight;//这里很奇怪对于是float的10.001 - 10 居然等于 0.0010004,这个估计和浮点数的加减法的以及精度有关,现在还没弄懂 
	low = tempF;
	
	//下面是把整数部分转成字符存储在数组中 
	int tempI = hight;
	do
	{
		*tempA++ = (char)(tempI % 10 + 48);
		tempI = tempI / 10;
		count++;
	}while(tempI);
	
	//存储的字符在数组中是倒序的,还想倒置过来,这里使用了前后交换元素的方法 
	tempA = a;
	for (int i = 0; i < count / 2; i++)
	{
		tempA[i] ^= tempA[count - i - 1] ^= tempA[i] ^= tempA[count - i - 1];
	}
	
	tempA[count++] = '.';//小数点 
	
	//下面是取出小数部分转成字符并存入数组中 
	tempA = &tempA[count];//存储的地址是在小数点后 
	float tp = 0.1;
	while(tempF > EPS)//精度限制,应为浮点数是不能和零直接比较的 
	{
		//tempF的变化规律举例:0.234 -> 0.034 -> 0.004 ->0 
		//low的变化规律举例:   0.234 -> 0.34 -> 0.4 -> 
		//pt 的变规律举例:    0.1 -> 0.01 -> 0.001 -> 
		tempF -= tp * (int)(low * 10);
		tp /= 10;
		*tempA++ = (int)(low * 10) + 48;
		low = low * 10 - (int)(low * 10);
		
	}
	
	*tempA = '\0';//字符串结尾 
	while (*a)
	{
		cout<<*a++;
	}
	return;
}
单列模式的创建
class MyCAS
{
	private:
		MyCAS(){cout<<"MyCAS构造函数执行了"<<endl;} //构造函数私有化 
	public:
		~MyCAS(){cout<<"MyCAS析构函数执行了"<<endl;}
	private:
		static MyCAS *myInstance;
	public:
		static MyCAS *GetInstance()
		{
			if (myInstance == NULL)//没有创建类就会去创建,已经创建了的就直接返回,故只能创建一个了 
			{
				myInstance = new MyCAS;
				static DeleteMyCAS deleMyCAS;//使用类中套类的方法释放内存,静态变量在程序结束后会自动释放。 
			}
			
			return myInstance;
		}
		
		void print()
		{
			cout<<"print()"<<endl;
		}
		
		class DeleteMyCAS  //类中嵌套类用于释放上面的内存,,, 
		{
			public:
				~DeleteMyCAS()
				{
					if (myInstance != NULL)
					{
						cout<<"释放myInstance的内存了"<<endl;
						delete myInstance;
					}
				}
			
		};
};
 
MyCAS *MyCAS::myInstance = NULL; //静态成员必须初始化,而且也只有这种的方式 


int main()
{
	{
		 MyCAS *p = MyCAS::GetInstance();
		 p->print();
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值