队列
与栈不同的是,队列是先进先出(First In First Out),这种结构在操作系统底层调用中广泛应用,
比如:键盘输入abc,先输入的a最先显示出来,依次b、c。
再比如:在操作系统中,将要处理的任务加入队列中,当cpu有空闲时,出队进行处理。
队列和栈一样,也有顺序队列和队链(不知道这个称呼对不对)。
这里我们讨论队链:
栈中使用的栈顶做标记,因为它只需要一个口就可以进出。
队列使用两个元素做标记,分别是队头和队尾(front and rear)。通过这两个指针的指向来指示队列的进出。
front 负责出队列(EnQueue)。
rear 负责进队列(DeQueue)。
看一个队列示意图:
这里需要两个结构:一个是队列的节点(Node)结构;另一个是指向队列的头尾的结构(该结构还可以包含队列大小等其他信息)。
0.队列的结构
typedef struct Node{ //队列的节点结构 int data; struct Node* next; }qNode,*pqNode; typedef struct Que{ //队列的指示结构 pqNode front,rear; int length; }linkQue;
1.队列的初始化
void init_queue(linkQue *que) { (*que).front = NULL; (*que).rear = NULL; (*que).length = 0; }
2.队列的进队
过程:
a.开辟一个新节点;
b.赋值,且新节点是最后一个元素,所以新节点的next指向NULL;
c.队列的尾节点的next指向新节点;
d.更新尾节点。
void EnQueue(linkQue *que,int elem) { if ((*que).front == NULL) { pqNode n = (pqNode)malloc(sizeof(qNode)); n->data = elem; n->next = NULL; (*que).front = n; (*que).rear = n; } else { pqNode n = (pqNode)malloc(sizeof(qNode)); n->data = elem; n->next = NULL; (*que).rear->next = n; (*que).rear = n; } (*que).length++; }
4.队列的出队
过程:
a.判断空;
b.定位要出队的节点(front指向的节点)
c.更新front指向节点(front的next节点)
d.提取要出队的节点信息,作为返回值。
e.free出队节点。
int DeQueue(linkQue *que) { if ((*que).front == NULL) { printf("no element in queue!\n"); return -1; } pqNode p = (*que).front; (*que).front=(*que).front->next; int re = p->data; free(p); (*que).length--; return re; }
测试:
void prt_que(linkQue que) { pqNode pos = que.front; while(que.rear->next != pos) { printf(" %d ",pos->data); pos = pos->next; } printf("\n"); }
主程序:
int _tmain(int argc, _TCHAR* argv[]) { int ary[10]= {2,65,4,34,35,86,68,35,1,54}; linkQue queue; pqNode list = NULL; init_queue(&queue); printf("add elem in queue!\n"); int i; for (i=0;i<10;i++) { EnQueue(&queue,ary[i]); } prt_que(queue); getchar(); int t; for(i=0;i<5;i++) { t = DeQueue(&queue); printf("out:%d\n",t); printf("now queue:"); prt_que(queue); } getchar(); return 0; }
结果: