队列:顺序存储的队列为了充分利用空间,可以进行循环利用,在笔记上看一下,不写了。队列先进先出,也是一种存储技术,利用队列来实现球钟。
球钟描述:球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。
工作原理:每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球钟表示时间的范围是从0:00到11:59。
现设初始时球队列的球数为27,球钟的三个指示器初态均为空。问,要经过多久,球队列才能回复到原来的顺序。
球钟问题程序流程图如下,S1、S5、S60分别为1分钟、5分钟、60分钟栈,队列出队成员赋值给x。
有了流程图代码实现就好办了:
include.h包含一些公用的头文件之类的东东。
#ifndef _INCLUDE_ #define _INCLUDE_ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <strings.h> typedef int datatype; #endif
队列定义及其操作函数的声明。
linksequeue.h
#ifndef _SQ_ #define _SQ_ #include "include.h" typedef struct sqnode{ datatype data; struct sqnode * next; }sqlinknode,*linksequeue; linksequeue sequeue_create(); int ensequeue(linksequeue sq,datatype data); datatype desequeue(linksequeue sq); /**if isempty return 1,else return 0***/ int sequeue_isempty(linksequeue sq); void sequeue_show(linksequeue sq); int sequeue_check(linksequeue sq); #endif
linkstack.h
栈的函数声明
#ifndef _STACK_ #define _STACK_ #include "include.h" typedef struct node{ int size; datatype data; struct node * next; }linknode,*linkstack; linkstack create(int n); int push(linkstack h,datatype data); /***if isempty return 1 else return 0***/ int isempty(linkstack h); datatype pop(linkstack h); void show(linkstack h); /**if isfull return 1,else return 0*****/ int isfull(linkstack h); #endif
linksequeue.c
队列操作函数的具体实现,本来可以用顺序循环队列比较好,但是为了练习链式存储的操作,特意用了链式队列。
关键是在出队的操作,要判断好临界值,否则很容易出现段错误。额....
#include "linksequeue.h" linksequeue sequeue_create() { linksequeue head; if((head = (linksequeue)malloc(sizeof(sqlinknode)))==NULL) { perror("malloc"); exit(-1); } head->next = NULL; return head; } int ensequeue(linksequeue head,datatype data) { linksequeue p; if((p = (linksequeue)malloc(sizeof(sqlinknode)))==NULL) { perror("malloc"); exit(-1); } p->data = data; p->next = head ->next; head->next = p; return 0; } datatype desequeue(linksequeue head) { datatype data; linksequeue tail,p; tail = head; if((tail->next)== NULL) { return -1; } while(((tail->next)!= NULL)&&(tail->next->next)!=NULL) { tail = tail->next; } p = tail->next; data = p->data; free(p); tail->next = NULL; return data; } int sequeue_isempty(linksequeue head) { if(head ->next == NULL) { return 1; } return 0; } void sequeue_show(linksequeue head) { linksequeue p; p = head; if(head ->next == NULL) { return ; } while(p ->next != NULL) { printf("data = %d\n",p->next->data); p = p->next; } } int sequeue_check(linksequeue head) { int i; linksequeue p,q; p = head->next; q = NULL; if(head->next==NULL) return 0; q = p->next; while((q!=NULL)&&(q->next!=NULL)) { if((p->data) < (q->data)) { return 0; } p = p->next; q = q->next; } return 1; }
linkstack.c
栈的操作,可以指定栈的大小,判断满栈和空栈不要忘记。
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <strings.h> #include "linkstack.h" linkstack create(int n) { linkstack h; if((h = (linkstack)malloc(sizeof(linknode)))==NULL) { perror("malloc"); return NULL; } h->size = n; h->next = NULL; return h; } int push(linkstack h,datatype data) { linkstack p; if(isfull(h)) { printf("fullllllllllllll\n"); return 1; } if((p = (linkstack)malloc(sizeof(linknode)))==NULL) { perror("malloc"); exit(-1); } p->size = 0; p->data = data; p->next = h->next; h->next = p; return 0; } int isfull(linkstack h) { int count = 0; linkstack p; p = h; while(p->next != NULL) { p = p->next; count ++; } if(count == h->size) { printf("is full\n"); return 1; } return 0; } int isempty(linkstack h) { if(h->next==NULL) { printf("is empty\n"); return 1; } return 0; } datatype pop(linkstack h) { datatype data; linkstack p = NULL; if(isempty(h)) { return 0; } p = h->next; h->next = p->next; data = p->data; free(p); return data; } void show(linkstack h) { linkstack p = NULL; if(isempty(h)) { printf("is empty!\n"); return ; } p = h->next; while(p != NULL) { printf("data = %d\n",p->data); p = p->next; } }
ballclock.c
main函数,逻辑根据上面的流程图写的,栈和队列的集中操作。
#include "linkstack.h" #include "linksequeue.h" #define N 27 int main(int argc,char * argv[]) { int count = 0; int i; datatype data,temp; linkstack s1,s5,s60; linksequeue sq; s1 = create(4); s5 = create(11); s60 = create(11); sq = sequeue_create(); for(i = 0;i<27;i++) { ensequeue(sq,i); } while(1) { data = desequeue(sq); count++; if(!isfull(s1)) { push(s1,data); } else { while(!isempty(s1)) { temp = pop(s1); ensequeue(sq,temp); } if(!isfull(s5)) { push(s5,data); } else { while(!isempty(s5)) { temp = pop(s5); ensequeue(sq,temp); } if(!isfull(s60)) { push(s60,data); } else { while(!isempty(s60)) { temp = pop(s60); ensequeue(sq,temp); } ensequeue(sq,data); if(sequeue_check(sq)) { sequeue_show(sq); break; } } } } } printf("count = %d\n",count); return 0; }
运算结果在除以60就是小时。