链队列的实现及其应用举例
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(2) 销毁队列ClearQueue(q) 释放队列占用的存储空间 ,包括链队头结点和所有 数据结点的存储空间。对应算法如下:
void ClearQueue(LiQueue *&q) { QNode *p=q->front,*r; if (p!=NULL) /*释放数据结点占用空间*/ { r=p->next; while (r!=NULL) { free(p); p=r;r=p->next; /*p和r指针同步后移*/ } } free(q); /*释放链队结点占用空间*/ }
game[food_x][food_y]= '*';
}
void moving()
{
int a,b; a= get_i(head); //取得头结点横坐标
b= get_j(head); //头结点纵坐标
switch(point) { case up: --a; break; case down: ++a; break; case left: --b; break; case right: ++b; break;
或离队,元素出队后,其后继元素就成为队首元素。
3.2.2 队列的链式存储结构及其基本运算的实现
链队组成: (1) 存储队列元素的单链表
(2) 指向队头和队尾指针的链队头结点
q front rear ∧ ∧
q front rear (b) 入队 3 个元素 q front rear (c) 出队 1 个元素 b c ∧ a b c ∧
• int main()
• { • cout<<"Using 'w,s,a,d'to control direction!!!“<<endl; • • //画框框和小蛇; InitFence();
•
• • • •
add_head(4,3,head);
add_head(4,4,head); add_head(4,5,head); get_food(); OutputF(); //显示食物
(3) 判断队列是否为空QueueEmpty(q)
若链队结点的 rear 域值为 NULL, 表示队列为空 , 返回1;否则返回0。对应算法如下:
int QueueEmpty(LiQueue *q) { if (q->rear==NULL) return 1; else return 0; }
(4) 入队列enQueue(q,e) 创建data域为e的数据结点*s。若原队列为空, 则将链队结点的两个域均指向*s结点,否则,将*s链 到单链表的末尾 ,并让链队结点的rear域指向它。 对应算法如下:
(5) 出队列deQueue(q,e)
若原队列不为空,则将第一个数据结点的data域 值赋给e,并删除之。若出队之前队列中只有一个结 点 ,则需将链队结点的两个域均置为 NULL, 表示队 列已为空。对应的算法如下:
int deQueue(LiQueue *&q,ElemType &e) { QNode *t; if (q->rear==NULL) return 0; /*队列为空*/ 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 1; }
•
• while (true) • { • char keydown= getch(); • //getch()返回键盘上读取的字符; • change_point(keydown); • while(!kbhit()) • //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 • { • system("cls"); //清屏函数; • moving(); • OutputF(); • Sleep(800); • //功 能: 执行挂起一段时间 • } • } • return 0; • }
case 's': point= down; break;
case 'a': point= left; break; case 'd': point= right; break; }
}
void get_food()
{
srand((unsigned int) time(NULL)); //做种子(程序运行时间); food_x= rand()%18+1; food_y= rand()%18+1;
链队列应用举例——贪吃蛇游戏设计
上下左右方向键控制贪吃蛇游动,不要撞到墙、不要碰到自己身体. 吃到食物,自身长长一节。
• 1)蛇的地盘怎么设计实现?
• 2)蛇怎么设计实现?
• 3)游动的控制?
• 4)食物的设计? • 5)吃到食物的处理?……
• 1)蛇的地盘的设计
• char game[20][20];
typedef { int i; struct node
int j;
node *next,*prior; }SnakeNode; //蛇结点 SnakeNode *head=NULL,*tail=NULL; tail i j i j i j i j
head
• • • • • • • •
int get_i(SnakeNode *&L) { return L->i; } int get_j(SnakeNode *&L) { return L->j; }
• • • • • • • • • •
//显示地盘; void OutputF() { for(int i=0; i<20; i++) { for(int j=0; j<20; j++) cout<<game[i][j]<<' '; cout<<endl; } }
• 2)蛇怎么设计实现?链式队列
• //画地盘; • void InitFence()
பைடு நூலகம்
//地盘;
• {
• • • • for(int i=0; i<20; i++) for(int j=0; j<20; j++) { if(i==0||i==19||j==0||j==19)
•
• • • } }
game[i][j]= '*';
else game[i][j]= ' ';
void enQueue(LiQueue *&q,ElemType e) { QNode *s; s=(QNode *)malloc(sizeof(QNode)); s->data=e; s->next=NULL; if (q->rear==NULL) /*若原链队为空,新结点是队首结点又是队尾结点*/ q->front=q->rear=s; else { q->rear->next=s; /*将*s结点链到队尾,rear指向它*/ q->rear=s; } }
(a) 链队初态
链列的入队和出队操作示意图
单链表中数据结点类型QNode定义如下:
typedef struct qnode
{ ElemType data; struct qnode *next; } QNode; /*数据元素*/
链队中头结点类型LiQueue定义如下:
typedef struct { QNode *front; QNode *rear; } LiQueue; /*指向单链表队头结点*/ /*指向单链表队尾结点*/
链队列的实现及其应用
蔡茂蓉
3.2.1 队列的定义
3.2.2 队列的链式存储结构及 其基本运算的实现 3.2.3 队列的应用例子
返回
3.2.1 队列的定义
队列简称队,它也是一种运算受限的线性表,其限 制仅允许在表的一端进行插入,而在表的另一端进行 删除。
我们把进行插入的一端称做队尾(rear),进行删除 的一端称做队首(front)。 向队列中插入新元素称为进队或入队,新元素进队 后就成为新的队尾元素;从队列中删除元素称为出队
• //插入头结点; • void add_head(int x,int y,SnakeNode *&L) • { • • • • • SnakeNode *q; q=(SnakeNode *)malloc(sizeof(SnakeNode)); q->i =x; q->j =y; q->next =head;
3)游动的控制?
• enum dir{up,down,left,right}; //枚举类型enum dir; • dir point; //枚举变量point: 控制方向; • int food_x; • int food_y;
void change_point(char keydown) { switch(keydown) { case 'w': point= up; break;
在链队存储中,队列的基本运算算法如下: (1) 初始化队列InitQueue(q) 构造一个空队列 , 即只创建一个链队头结点 , 其 front 和 rear 域均置为 NULL, 不创建数据元素结点。 对应算法如下:
void InitQueue(LiQueue *&q) { q=(LiQueue *)malloc(sizeof(LiQueue)); q->front=q->rear=NULL; }
}
if(a==19||b==19||a==0||b==0) //判断是否撞墙; {
cout<<"game over!!!"<<endl;
exit(0); }
• if(a==food_x && b==food_y) //吃food; • { • • • } • • • • • } } else{ add_head(a,b,head); //插入头结点; delete_tail(); //删除尾结点; add_head(a,b,head); get_food();
建立的链队列的头指针存放在L中
• //删除尾结点; • void delete_tail() • { • • • • • • • • • • } } delete p; else{ tail= tail->prior; tail->next= NULL; SnakeNode *p =tail; game[get_i(tail)][get_j(tail)]= ‘ ’;//把尾结点的坐标 //表示的'*'置为空格; if(tail==head) //删除的时候,只有一个结点了 tail= head= NULL;
•
• • • • • • }
q->prior =NULL;
//准备插入的结点
//如果head不为真,表示插入的
if(head) head->prior =q; head =q; if(!tail) tail =head; 此时需要修改尾指针 game[x][y]= '*'; L=head;//
时候链表非空,新插入的结点作为头结点 //如果tail为空,表示插入的时候是空表,