队列(queue)是一种先进先出(FIFO)的线性表。只允许在一端进行插入,而在另一端删除元素。
允许插入的一端叫做队尾,允许删除的一端叫做队头。
双端队列(deque):限定插入和删除操作在表两端进行的线性表。
双端队列在一些限定条件下可以退化为:
(1)普通队列(只能在一端插入而另外一端删除)
(2)两个栈底相连的栈
队列 / 双端队列的定义:
由于可以在双端操作,所以肯定得有一个head,一个rear(tail)。我觉得确实用一个多的空头表示比较合适,然后头的data可以表示队列中有多少元素。
注意1:删除队列头时,如果被删除的元素是队列中最后一个元素时,一定要记得更新尾结点为NULL!
注意2:双端队列在队尾删除的时候,由于没有保存前向指针,需要从head从头遍历到tail的前一个,还要注意考虑只有一个结点的特殊情况。
代码如下:
#include
#include
struct Node
{
struct Node* next;
int data;
};
struct Deque
{
struct Node* head;
struct Node* tail;
};
int deque_init(struct Deque* dq)
{
dq->head = (struct Node*)malloc(sizeof(struct Node));
if(!dq->head)
{
return -1;
}
dq->tail = (struct Node*)malloc(sizeof(struct Node));
if(!dq->tail)
{
return -1;
}
dq->head->data = dq->tail->data = 0;
dq->head->next = dq->tail->next = NULL;
return 0;
}
void deque_print(struct Deque* dq)
{
struct Node* ptr = dq->head;
while(ptr->next!=NULL)
{
ptr = ptr->next;
printf("%d ", ptr->data);
}
printf("\n");
}
int deque_length(struct Deque* dq)
{
if(!dq->head)
{
return 0;
}else
{
return dq->head->data;
}
}
void deque_free(struct Deque* dq)
{
struct Node* ptr = dq->head;
struct Node* ptr2 = NULL;
// Free all except tail
while(ptr!=NULL)
{
ptr2 = ptr->next;
free(ptr);
ptr = ptr2;
}
// Free tail
if(dq->tail)
{
free(dq->tail);
}
dq->head = dq->tail = NULL;
}
int deque_head_enqueue(struct Deque* dq, int data)
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
if(!new_node)
{
return -1;
}
new_node->next = NULL;
new_node->data = data;
new_node->next = dq->head->next;
dq->head->next = new_node;
dq->head->data++;
// If new node was also tail
if(new_node->next==NULL)
{
dq->tail->next = new_node;
}
}
int deque_head_dequeue(struct Deque* dq, int* data)
{
struct Node* free_node = dq->head->next;
if(free_node)
{
*data = free_node->data;
dq->head->next = free_node->next;
// If only one node
if(free_node->next==NULL)
{
dq->tail->next = NULL;
}
free(free_node);
dq->head->data--;
return 0;
}else
{
return -1;
}
}
int deque_tail_enqueue(struct Deque* dq, int data)
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
if(!new_node)
{
return -1;
}
new_node->data = data;
new_node->next = NULL;
dq->head->data++;
// if list is empty
if(dq->tail->next==NULL)
{
dq->head->next = new_node;
dq->tail->next = new_node;
} else
{
dq->tail->next->next = new_node;
dq->tail->next = new_node;
}
}
int deque_tail_dequeue(struct Deque* dq, int* data)
{
struct Node* free_node = dq->tail->next;
struct Node* ptr = NULL;
if(!free_node)
{
return -1;
}
*data = free_node->data;
// Find node
ptr = dq->head;
free_node = dq->tail->next;
while(ptr->next!=free_node)
{
ptr = ptr->next;
}
// Only one node
if(ptr==dq->head)
{
free(free_node);
dq->head->next = dq->tail->next = NULL;
dq->head->data = 0;
}else
{
free(free_node);
ptr->next = NULL;
dq->tail->next = ptr;
dq->head->data--;
}
return 0;
}
int deque_head(struct Deque* dq, int* data)
{
struct Node* head = dq->head->next;
if(head!=NULL)
{
*data = head->data;
return 0;
}else
{
return 1;
}
}
int deque_tail(struct Deque* dq, int* data)
{
struct Node* tail = dq->tail->next;
if(tail!=NULL)
{
*data = tail->data;
return 0;
}else
{
return 1;
}
}
int main()
{
struct Deque dq;
int i;
int data;
if(deque_init(&dq))
{
printf("deque init fail.\n");
return -1;
}
//deque_head_enqueue(&dq, 888);
//deque_tail_enqueue(&dq, 888);
//deque_tail_dequeue(&dq, &data);
// Head
if(!deque_head(&dq, &data))
{
printf("Head:%d\n", data);
}else
{
printf("Deque is empty, no head\n");
}
// Tail
if(!deque_tail(&dq, &data))
{
printf("Tail:%d\n", data);
}else
{
printf("Deque is empty, no tail\n");
}
// Length
printf("Length:%d\n", deque_length(&dq));
// Head Enqueue
//for(i=0;i<10;i++)
//{
//deque_head_enqueue(&dq, i);
//}
//for(i=0;i<8;i++)
//{
//deque_head_dequeue(&dq, &data);
//}
// Tail Enqueue
for(i=0;i<10;i++)
{
deque_tail_enqueue(&dq, i);
}
for(i=0;i<8;i++)
{
deque_tail_dequeue(&dq, &data);
}
deque_print(&dq);
printf("Length:%d\n", deque_length(&dq));
// Tail
if(!deque_tail(&dq, &data))
{
printf("Tail:%d\n", data);
}else
{
printf("Deque is empty, no tail\n");
}
deque_free(&dq);
return 0;
}