知识点总结报告
知识点:
队列
(原理)队列是一种操作受限制的线性表,其限制为仅允许在表的一端(队尾)进行插入操作,在表的另一端(队首)进行删除操作。特点是先进先出。
顺序队
typedef struct
{ ElemType data[MaxSize]; //存放队中元素
int front,rear; //队头队尾指针
}SqQueue; //顺序队类型
队空条件 q->front==q->rear
队满条件 q->rear==MaxSize-1(data数组的最大下标)
元素e的进队操作:先将rear增1,然后将元素e放在data数组的rear位置
出队操作:先将front增1,然后取出data数组中front位置的元素
初始化队列InitQueue(&q)
void InitQueue(SqQueue *&q)
{ q=(SqQueue *)malloc(sizeof(SqQueue));
q->front=q->rear=-1;
}
销毁队列DestroyQueue(&q)
void DestroyQueue(SqQueue *&q)
{ free(q);
}
判断队列是否为空QueueEmpty(q)
bool QueueEmpty(SqQueue *q)
{ return(q->front==q->rear);
}
进队列enQueue(&q,e)
bool enQueue(SqQueue *&q,ElemType e)
{ if(q->rear==MaxSize-1) //队满上溢出
return false; //返回假
q->rear++; //队尾增1
q->data[q->rear]=e; //rear位置插入元素e
return true; //返回真
}
出队列deQueue(&q,&e)
bool deQueue(SqQueue *&q,ElemType &e)
{ if(q->front==q->rear) //队空下溢出
return false;
q->front++;
e=q->data[q->front];
return true;
}
环形队
队头指针front循环增1:front=(front+1)%MaxSize
队尾指针rear循环增1:rear=(rear+1)%MaxSize
初始化队列InitQueue(&q)
void InitQueue(SqQueue *&q)
{ q=(SqQueue *)malloc(sizeof(SqQueue));
q->front=q->rear=0;
}
销毁队列DestroyQueue(&q)
void DestroyQueue(SqQueue *&q)
{ free(q);
}
判断队列是否为空QueueEmpty(q)
bool QueueEmpty(SqQueue *q)
{ return(q->front==q->rear);
}
进队列enQueue(&q,e)
bool enQueue(SqQueue *&q,ElemType e)
{ if((q->rear+1)%MaxSize==q->front) //队满上溢出
return false;
q->rear=(q->rear+1)%MaxSize;
q->data[q->rear]=e;
return true;
}
出队列deQueue(&q,&e)
bool deQueue(SqQueue *&q,ElemType &e)
{ if(q->front==q->rear) //队空下溢出
return false;
q->front=(q->front+1)%MaxSize;
e=q->data[q->front];
return true;
}
链队
typedef struct qnode //链队中数据结点类型
{ ElemType data; //存在元素
struct qnode *next; //下一个结点指针
}DataNode;
typedef struct //链队头结点类型
{ DataNode *front; //指向队首结点
DataNode *rear; //指向队尾结点
}LinkQuNode;
初始化队列InitQueue(&q)
void InitQueue(LinkQuNode *&q)
{ q=(LinkQuNode *)malloc(sizeof(LinkQuNode));
q->front=q->rear=NULL;
}
销毁队列DestroyQueue(&q)
void DestroyQueue(LinkQuNode *&q)
{ DataNode *pre=q->front,*p; //pre指向队首结点
if(pre!=NULL)
{ p=pre->next; //p指向结点pre的后继结点
while(p!=NULL) //p不空循环
{ free(pre); //释放pre结点
pre=p;p=p->next; //pre.p同步后移
}
free(pre); //释放最后一个数据结点
}
free(q); //释放链队结点
}
判断队列是否为空QueueEmpty(q)
bool QueueEmpty(LinkQuNode *q)
{ return(q->rear==NULL);
}
进队列enQueue(&q,e)
bool enQueue(LinkQuNode *&q,ElemType e)
{ DataNode *p;
p=(DataNode *)malloc(sizeof(DataNode)); //创建新结点
p->data=e;
p->next=NULL;
if(q->rear==NULL) //若链队为空,则新结点既是队首结点又是队尾结点
q->front=q->rear=p;
else //若链队不空
{ q->rear->next=p; //将结点p链到队尾,并将rear指向它
q->rear=p;
}
}
出队列deQueue(&q,&e)
bool deQueue(LinkQuNode *&q,ElemType &e)
{ DataNode *t;
if(q->rear==NULL) //原来队列为空
return false;
t=q->front; //t指向首结点
if(q->front==q->rear) //原来队列中只有一个数据结点时
q->front=q->rear=NULL;
else //原来队列中有两个或两个以上结点时
q->front=q->front->next;
e=t->data;
free(t);
return true;
}
(例题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1387
In a team queue each element belongs to a team. If an element enters the queue, it first searches the queue from head to tail to check if some of its teammates (elements of the same team) are already in the queue. If yes, it enters the queue right behind them. If not, it enters the queue at the tail and becomes the new last element (bad luck). Dequeuing is done like in normal queues: elements are processed from head to tail in the order they appear in the team queue.
Your task is to write a program that simulates such a team queue.
Finally, a list of commands follows. There are three different kinds of commands:
ENQUEUE x - enter element x into the team queue
DEQUEUE - process the first element and remove it from the queue
STOP - end of test case
The input will be terminated by a value of 0 for t.
题目分析:
找一个数组记录这个小队是否在大队里,且大队列用一个二维数组存,其中每一行的首元素表示为这一行是哪个小队的,之后根据这个正要进入大队列的成员确定其所在小队是否已经在大队列中,如果在则放到这个小队的那一行的最后,如果不在则在大队列中的最后表示这个新的小队的存在,然后再这一个小队的这一行的第一个元素为这个成员。然后在出队伍的时候,依次从大队列的第一个小队的第一个成员出,因为这题非常容易超时,所以把千万避免遍历,所以要把大队列的队首记下来,大队列的队尾记录下来,每个小队的第一个元素记下来,每个小队的个数记下来。还是因为时间问题,这题千万不能移动元素,因为这样非常耗时,所以要改变的是记录大队列队首和大队列队尾的数值,还有改变小队的队首与每个小队的个数;(也是因为这个原因,没办法用链表进行,只能用数组进行);
题解代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> int number[1005]; int s_mumber[1000005]; int s_num[5005][1005]; int main() { int t,j,i,num=0,n,ttt,start; char ss[10]; while(scanf("%d",&t)!=EOF&&t!=0) { for(i=0;i<t;i++) { scanf("%d",&n); for(j=0;j<n;j++) { scanf("%d",&ttt); number[j]=0; s_mumber[ttt]=i; } } int times=0; num++;start=0; printf("Scenario #%d\n",num); while(1) { scanf("%s",ss); if(ss[0]=='E') { scanf("%d",&ttt); i=s_mumber[ttt]; if(number[i]==0) { s_num[times][0]=i; s_num[times][1]=1; s_num[times][2]=3; s_num[times][3]=ttt; number[i]=1; times++; } else { for(j=start;j<times;j++) if(i==s_num[j][0]) break; s_num[j][1]++; s_num[j][s_num[j][2]+s_num[j][1]-1]=ttt; } } else if(ss[0]=='S') break; else if(ss[0]=='D') { if(s_num[start][1]==0) { number[s_num[start][0]]=0; start++; printf("%d\n",s_num[start][s_num[start][2]]); s_num[start][2]++; s_num[start][1]--; } else { printf("%d\n",s_num[start][s_num[start][2]]); s_num[start][2]++;s_num[start][1]--; } } } printf("\n"); } return 0; }