622.设计循环列表

题目:如下图

答案:如下图

//使用数组的方式进行求解
typedef struct {
	int* _a;
	int _front;
	int _rear;
	int _k;
} MyCircularQueue;
//开辟数组空间多开一个并且指针也开辟空间
MyCircularQueue* myCircularQueueCreate(int k) {
	MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	q->_a= (int*)malloc(sizeof(int) * (k + 1));
	q->_k = k;
	q->_front = 0;
	q->_rear = 0;

	return q;
}
//用到相应函数进行提前声明
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
bool myCircularQueueIsFull(MyCircularQueue* obj) 
//向循环队列插入一个元素。如果成功插入则返回真。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if (myCircularQueueIsFull(obj))
	{
		return false;
	}

	obj->_a[obj->_rear] = value;
	++obj->_rear;
    obj->_rear%=(obj->_k + 1);
	return true;
}
//从循环队列中删除一个元素。如果成功删除则返回真
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return false;
	}
	++obj->_front;
    obj->_front %= (obj->_k + 1);//仅仅是做了,但是没有去赋值	
	return true;
}
//从队首获取元素。如果队列为空,返回-1
int myCircularQueueFront(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	else
	{		
		return obj->_a[obj->_front];
	}
}
//从获取队尾元素。如果队列为空,返回-1
int myCircularQueueRear(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
		return -1;
	else
		if (obj->_rear == 0)
			return(obj->_a[obj->_k]);
	    return obj->_a[obj->_rear-1];
}
//为空返回1,不为空返回0
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
	return obj->_front ==obj->_rear
}
//为满返回1,不为满返回0
bool myCircularQueueIsFull(MyCircularQueue* obj) {
	return (obj->_rear+1)%(obj->_k +1) == obj->_front;
}
//释放
void myCircularQueueFree(MyCircularQueue* obj) {
	free(obj->_a);
	free(obj);
}

解析:

(1)使用数组的方式进行求解

typedef struct {
    int* _a;
    int _front;
    int _rear;
    int _k;
} MyCircularQueue; 

数组便于判断循环队列中的空与满

开辟空间时多开辟一个空间用于判断空满,当_front==_rear时循环队列为空,由于留了一个结点用于判断满,故当且仅空一个结点时为满,,即_front==_rear+1时循环队列为满,,,当_rear为最后一个结点时采用 (_rear+1)%(k+1)来使其为0      此时0=0  故采用 _front==(_rear+1)%(k+1)来判断循环队列为满

(2)多开辟一个数组空间并且开辟结构体空间

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->_a= (int*)malloc(sizeof(int) * (k + 1));
    q->_k = k;
    q->_front = 0;
    q->_rear = 0;

    return q;
}

(3)用到相应函数进行提前声明

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj) ;

(4)向循环队列插入一个元素。如果成功插入则返回真

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }

    obj->_a[obj->_rear] = value;
    ++obj->_rear;
    obj->_rear%=(obj->_k + 1);
    return true;
}

(5)使用判断是否满的函数进行判断如果满的话就不能插入,返回false

当_rear的值加一后可能超过_k的值出现数组越界,这时候就采取obj->_rear%=(obj->_k + 1)的操作使其成为0;

执行完之后返回true

       

(6)从循环队列中删除一个元素。如果成功删除则返回真

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    ++obj->_front;
    obj->_front %= (obj->_k + 1);
    return true;
}

先用判断是否为空的函数进行判断,若为空则无法进行删除,返回false

直接将++obj->_front即可完成删除操作,其本质为下标加一,访问首元素时是用下标进行访问,下标加一访问的是下一个元素,值得注意的是front加一后有可能出现数组越界,图解和(5)中类似这里就不再列举了

(7)从队首获取元素。如果队列为空,返回-1

int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {        
        return obj->_a[obj->_front];
    }
}

当数组为空的时候无法在队首获取元素,使用判断是否为空的函数进行判断,若为空则返回-1

不为空则return obj->_a[obj->_front]

(8)从获取队尾元素。如果队列为空,返回-1

int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
        return -1;
    else
        if (obj->_rear == 0)
            return(obj->_a[obj->_k]);
        return obj->_a[obj->_rear-1];
}

当数组为空的时候无法在队尾获取元素,使用判断是否为空的函数进行判断,若为空则返回-1

不为空则return obj->_a[obj->_rear-1]

特别的当_rear在0的时候obj->_rear-1等于-1,用obj->_a[obj->_rear-1]进行访问则包出现数组越界,这时候用if语句判断,返回return(obj->_a[obj->_k]);即可

(9)判断是否为空,为空返回1,不为空返回0

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->_front ==obj->_rear
}

        判断是否为满,为满返回1,不为满返回0
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->_rear+1)%(obj->_k +1) == obj->_front;
}

 

开辟空间时多开辟一个空间用于判断空满,当_front==_rear时循环队列为空,由于留了一个结点用于判断满,故当且仅空一个结点时为满,,即_front==_rear+1时循环队列为满,,,当_rear为最后一个结点时采用 (_rear+1)%(k+1)来使其为0      此时0=0  故采用 _front==(_rear+1)%(k+1)来判断循环队列为满

(10)释放循环队列


void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->_a);
    free(obj);
}

使用free()函数释放数组以及obj结构体

到这里我们解题完毕

如果对您有帮助的话点一个免费的赞和收藏叭!

由于作者水平不足,如果有任何错误,麻烦读者评论在评论区指点一下,谢谢!

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值