一、循环队列
关键掌握点:
- 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;
}