数据结构——受限表之队列
队列:
定义:
队列是先进先出(FIFO)的线性表。它只允许在表的一端进行插入元素,另一端删除元素。在队列中,允许插入的一端称为队尾,允许删除的一端称为队头。设Queue=(a1,a2,……an),则a1是队头元素,an是队尾元素,入队、出队的次序都是a1到an。
队列的顺序结构实现:
定义:
#define MAXSIZE 100
typedef int ElemType;
typedef struct{ElemType data[MAXSIZE];int front;int rear;//定义front代表队头序号,rear代表队尾序号
}Queue;
初始化:
void initQueue(Queue *Q)
{Q->front=0;Q->rear=0;
}//初始时,队头和队尾都指向数组首
判断队列是否为空:
bool IsEmpty(Queue *Q)
{if(Q->front==Q->rear){return 1;}else return 0;
}//如果队头和队尾是同一个位置的元素,说明队列里没有元素,那么队列为空
出队:
ElemType DeQuene(Queue *Q)
{if(IsEmpty(Q)) return 0;else{ElemType e=Q->data[Q->front];Q->front+=1;return e;}
}//出队是从队头出元素的,我们只需要把front后移一位,让它指向下一个元素,那么前边的元素就不在队列里了,出队成功
入队:
入队是在队尾进行的,由于之前咱们出队是直接让front后移的,所以比front小的索引的数组元素此时是无意义地占用了数组空间。如果数组还有空间让我们插入元素,我们就可以直接插入,但如果数组没有多余空间了,我们就要利用掉被无意义占用的空间,调整队列(整体向前平移),腾出空间后再入队。下一部分讲的就是如何调整空间。
int EQuene(Queue *Q,ElemType e)
{if(Q->rear>=MAXSIZE){if(!QueueFull(Q)){return 0;}}Q->data[Q->rear]=e;Q->rear+=1;return 1;
}
调整队列:
int QueueFull(Queue *Q)
{if(Q->front>0){int step=Q->front;for(int i=Q->front;i<=Q->rear;i++){Q->data[i-step]=Q->data[i];}Q->front=0;Q->rear=Q->rear-step;return 1;}else{printf("真满了\n");return 0;}
}
获取队头数据:
ElemType GetHead(Queue *Q)
{if(Q->front==Q->rear){printf("队列是空的\n");}else{return Q->data[Q->front];}
}
总结代码:
#include<stdio.h>
#define MAXSIZE 100
typedef int ElemType;
typedef struct{ElemType data[MAXSIZE];int front;int rear;
}Queue;
void initQueue(Queue *Q)
{Q->front=0;Q->rear=0;
}
bool IsEmpty(Queue *Q)
{if(Q->front==Q->rear){return 1;}else return 0;
}
ElemType DeQuene(Queue *Q)
{if(IsEmpty(Q)) return 0;else{ElemType e=Q->data[Q->front];Q->front+=1;return e;}
}
int QueueFull(Queue *Q)
{if(Q->front>0){int step=Q->front;for(int i=Q->front;i<=Q->rear;i++){Q->data[i-step]=Q->data[i];}Q->front=0;Q->rear=Q->rear-step;return 1;}else{printf("真满了\n");return 0;}
}
int EQuene(Queue *Q,ElemType e)
{if(Q->rear>=MAXSIZE){if(!QueueFull(Q)){return 0;}}Q->data[Q->rear]=e;Q->rear+=1;return 1;
}
ElemType GetHead(Queue *Q)
{if(Q->front==Q->rear){printf("队列是空的\n");}else{return Q->data[Q->front];}
}
int main()
{Queue queue;initQueue(&queue);printf("%d\n",IsEmpty(&queue));EQuene(&queue,10);EQuene(&queue,20);EQuene(&queue,30);printf("%d\n",DeQuene(&queue));printf("%d\n",DeQuene(&queue));QueueFull(&queue);printf("%d\n",queue.front);return 0;
}
动态内存分配的总代码和注释:
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct node{ElemType data;struct node *prev,*next;
}Node;
Node* initList()
{Node* head=(Node*)malloc(sizeof(Node));head->data=0;head->next=NULL;return head;
}
int insertHead(Node *L,ElemType e)
{Node *p=(Node*)malloc(sizeof(Node));p->data=e;p->prev=L;p->next=L->next;if(L->next!=NULL) L->next->prev=p;L->next=p;
}
Node* FindTail(Node* L)
{Node* p=L;while(p->next!=NULL){p=p->next;}return p;
}
Node* insertTail(Node *tail,ElemType e)
{Node *p=(Node*)malloc(sizeof(Node));p->data=e;p->next=NULL;p->prev=tail;tail->next=p;return p;
}
int insertNode(Node *L,int pos,int e)
{Node*p=L;int i=0;while(i<pos-1){p=p->next;i++;if(p==NULL) return 0;}Node*q=(Node*)malloc(sizeof(Node));q->data=e;q->next=p->next;p->next->prev=q;p->next=q;q->prev=p;return 1;
}
void freeList(Node* L)
{Node* p=L;Node* q;while(p!=NULL){q=p->next;free(p);p=q;}L->next=NULL;
}
void ListNode(Node* L)
{Node *p=L->next;while(p!=NULL){printf("%d ",p->data);p=p->next;}printf("\n");
}
int deleteNode(Node* L,int pos)
{Node*p=L;int i=0;while(i<pos-1){p=p->next;i++;if(p==NULL) return 0;}if(p->next==NULL) return 0;Node* q=p->next;p->next=q->next;q->next->prev=p;free(q);return 1;
}
int main()
{Node* list=initList();insertHead(list,10);insertHead(list,20);insertHead(list,30);ListNode(list);insertTail(FindTail(list),40);insertTail(FindTail(list),50);ListNode(list);insertNode(list,2,80);ListNode(list);deleteNode(list,3);ListNode(list);freeList(list);return 0;}
队列的链式结构:
这里我们说一下思路,实现其实有了前面的基础就很容易。
第一种方法就是建立链表,尾插法输入数据,然后从头结点后面删除数据。(参考链表章节的各种操作)
第二种方法还是建立链表,只不过继续设置front指向队列链表的队头,rear指向队列链表的队尾,设置一个计数器length来记录链表的长度。这样子的好处是可以快速实现队列的入队、出队操作。(第一种入队需要遍历链表查找队尾)。
下面我给出了第二种方法建立链表的操作。其余的操作其实和前边讲的都类似,此处不再过多赘述。
typedef int ElemType;
struct node
{;ElemType data;struct node* next;
}Node;
struct queue
{struct Node* front;struct Node* rear;int length;
}Queue;