第3章 栈和队列 3.1 栈 3.2 队列 3.3 应用.

Slides:



Advertisements
Similar presentations
计算机三级考试C语言上机试题专题.
Advertisements

数据结构.
数据结构概论 第2章 线性表 董黎刚 浙江工商大学信电学院
计算机硕士专业基础—C语言 赵海英
数据结构——树和二叉树 1/96.
第六章 树和二叉树.
数据结构算法 模拟练习及解答二 绍兴文理学院 计算机系计算机应用教研室.
数据结构 第6章 树和二叉树 什么是树和二叉树?? 二叉树的遍历 数据结构.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第2章 线性表 2.1 线性表的概念及运算 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 一元多项式的表示及相加.
数据结构与算法 数据结构与算法实验
第三章 堆疊與佇列的基本應用 3-1 簡介堆疊(Stack) 3-2 迷宮問題研究 3-3 佇列(queue)的介紹
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
Linked List Operations
單向鏈結串列 Singly Linked Lists.
第2章 线性表 线性结构 是一个数据元素的有序集合。.
第6章 佇列(Queues) 6-1 佇列的基礎 6-2 佇列的表示法 6-3 環狀佇列 6-4 雙佇列.
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
佇列 (Queue).
資料結構 第5章 佇列.
C++程序设计 第二讲 清华大学软件学院.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
Ch.3 栈和队列 黄刘生 中国科学技术大学计算机系 国家高性能计算中心(合肥)
线性表小结 元素之间的线性关系 顺序表 顺序表:元素相邻存储 单链表:后继指针链接 一维数组 给定下标随机存取
cn/~dongeliu/dsa.html 刘 东 信息学院6系 中国科学技术大学
第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 线性表的应用 2.5 有序表 本章小结.
第3章 栈和队列(二) 1/.
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第十章 C高级程序应用—链表* 10.1链表的基本概念 10.2单向链表 10.3双向链表 10.4应用举例.
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
Introduction to the C Programming Language
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
第三章 栈与队列 £3.1 栈 £3.3 队列 £3.2 栈的应用举例 £3.1.1 栈的定义 £3.1.2 栈的顺序存储结构
第三章 栈和队列 3.1 栈 3.2 栈的应用举例 3.3 栈与递归的实现 3.4 队列.
第3章 栈和队列(一).
第三章 栈和队列.
数据结构 Data Structure 中南大学 主讲人:王国军,郑瑾 中南大学信息院计科系
資料結構與C++程式設計進階 堆疊與佇列(Stack & Queue) 講師:林業峻 CSIE, NTU 6/ 21, 2010.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
内容回顾 线性表的定义和特点 线性表的顺序存储及查找、插入和删除.
栈和队列练习.
6.3 遍历二叉树和线索二叉树(知识点二) 遍历二叉树 一、问题的提出
第三章 栈和队列.
#define STACK_INIT_SIZE 10
資料結構 第4章 堆疊.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
自我參考結構 (self-reference – 1)
7.1 广义表的概念 广义表是n(n≥0)个数据元素组成的序列,其中每个数据元素或是单个数据元素(简称原子),或仍然是一个广义表 。
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第十章 结构体与链表 西安工程大学.
第6章 数组与广义表 6.1 数组的定义及其基本操作 6.2 数组的顺序存储结构 6.3 矩阵的压缩存储 6.4 广义表的概念
程式結構&語法.
第六章 树和二叉树 学习要点 理解树的定义和基本术语,重点了解二叉树的定义、性质、存储结构; 掌握二叉树遍历的递归算法及它的典型运算;
Linked Lists Prof. Michael Tsai 2013/3/12.
浙江长征职业技术学院—计算机与信息技术系—相方莉制作
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
第二章 线性表.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第 六 讲 栈和队列(一).
第1章 数据结构基础概论 本章主要介绍以下内容 数据结构研究的主要内容 数据结构中涉及的基本概念 算法的概念、描述方法以及评价标准.
Chapter 2 Entity-Relationship Model
第7章 图.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
本节内容 1.二叉排序树的定义 2.二叉排序树的查找操作 3.二叉排序树的插入操作 4.二叉排序树的删除操作 5.二叉排序树的总结
Presentation transcript:

第3章 栈和队列 3.1 栈 3.2 队列 3.3 应用

汉诺塔 进 出 排队买票 进 出 栈和队列是两种重要的线性结构 栈和队列是操作受限的线性表

3.1 栈 3.1.1 栈的基本概念 进栈(Push) 出栈(Pop) 栈顶 top en-1 en-2 … e1 栈底bottom e0

栈的基本运算 : InitStack(s)初始化操作 IsEmpty(s)判断栈空函数 IsFull(s)判断栈满函数 Push(s,x)压栈操作 Pop(s)出栈函数 GetTop(s)获取栈顶元素函数 EmptyStack(s)清空栈操作 DestroyStack ()销毁栈

3.1.2栈的顺序存储结构 栈的顺序存储结构称为顺序栈 A B C top -1 4 3 2 1 (a)空栈 (b)元素A进栈 (c)元素B、C进栈 ( d)出栈一次 ( e)出栈二次

顺序栈类型定义如下: #define StackSize 100 /*顺序栈的初始分配空间*/ typedef struct sqst { DataType data[StackSize]; /*栈中元素*/ int top; /*栈指针*/ }SeqStack;

顺序栈的基本运算 : void InitStack(SeqStack *sq) { (1)初始化栈运算算法 创建一个空栈,并将栈顶下标top初始化为-1。 void InitStack(SeqStack *sq) { sq=(SeqStack *)malloc(sizeof(SqStack)); sq->top=-1 ; }

(2)进栈运算算法 { if(sq->top== StackSize-1)/*栈满*/ return 0; else int Push(SeqStack *sq,DataType x) { if(sq->top== StackSize-1)/*栈满*/ return 0; else sq->top++; sq->data[sq->top]=x ; return 1; } }

(3)出栈运算算法 int Pop(SeqStack *sq,DataType x) { if(sq->top==-1) /*栈空*/ return 0; else { x=sq->data[sq->top]; sq->top--; return 1; } }

(4)取栈顶元素运算算法 int GetTop(SeqStack *sq,DataType x) { if(sq->top==-1) /*栈空*/ return 0; else x=sq->data[sq->top]; return 1; }

(5)判断栈空运算算法 int StackEmpty(SeqStack *sq) { if(sq->top==-1) return 1; else return 0; }

struct stnode *next ; /*指针域*/ 3.1.3栈的链式存储结构 … ∧ ls data next 栈顶指针 栈顶 栈底 typedef struct stnod { DataType data; /*存储结点数据*/ struct stnode *next ; /*指针域*/ }LinkStack;

链栈的基本运算算法: (1)初始化栈运算算法 void InitStack(LinkStack *ls) { ls=NULL; }

(2)判断栈空运算算法 int StackEmpty(LinkStack *ls) { if(ls==NULL) return 1; else return 0;}

(3)进栈运算算法 void Push(LinkStack *ls,DataType x) { LinkStack *p; p=(LinkStack*)malloc(Sizeof(LinkStack)); p->data=x; p->next=ls; ls=p; }

(4)出栈运算算法 { LinkStack *p; if(ls==NULL) /*栈空,下溢出*/ return 0; else int Pop(LinkStack *ls,DataType x) { LinkStack *p; if(ls==NULL) /*栈空,下溢出*/ return 0; else { p=ls; x=p->data; ls=p->next; free(p); return 1; }}

(5)取栈顶元素运算算法 int GetTop(LinkStack*ls,DataType x) { if(ls==NULL) /*栈空,下溢出*/ return 0; else x=ls->data; return 1; } }

3.2 队列 3.2.1队列的基本概念 队列限制插入在一端进行,删除在另一端进行的线性表。 出列 入列 队尾(rear) 队首(front)

队列的基本操作: 1)InitQueue(Q):构造一个空队列Q。 2)QueueEmpty(Q):判断队列是否为空。 3)QueueLength(Q):求队列的长度。 4)GetHead(Q):返回Q的队头元素。 5)EnQueue(Q,x):插入x为Q的新的队尾元素。 6)DeQueue(Q):删除Q的队头元素。 7)C1earQueue(Q):清除队列Q中的所有元素。

3.2.2队列的链式存储结构 队首 队尾 … front 队首指针 ^ rear 队尾指针

链队的类型定义如下: typedef struct QNode { DataType data; struct QNode *next; }QType; /*链队中结点的类型*/ typedef struct qptr { QType *front,*rear; }LinkQueue; /*链队类型*/

void InitQueue(LinkQueue *lq) { lq->rear=lq->front=NULL; } (1)初始化队列运算算法 /*置队列lq的rear和front均为NULL*/ void InitQueue(LinkQueue *lq) { lq->rear=lq->front=NULL; }

(2)入队运算算法 voidEnQueue(LinkQueue*lq,DataType x) { QType *s; /*创建新结点,插入到链队的末尾*/ s=(QType *)malloc(sizeof(QType)); /*创建新结点,插入到链队的末尾*/ s->data=x;s->next=NULL; if(lq->front==NULL&&lq->rear==NULL) /*空队*/ lq->rear=lq->front=s; else { lq->rear->next=s; lq->rear=s; } }

(3)出队运算算法 int DeQueue(LinkQueue *lq,DataType x) { QType *p; if(lq->front==NULL&&lq->rear==NULL) return 0; /*空队*/ p=lq->front; x=p->data; lq->front=p->next; if(lq->rear==lq->front) lq->rear=lq->front=NULL; /*若原队列中只有一个结点,删除后队列变空*/ free(p); return x;}

(4)取队头元素运算算法 { if(lq->front==NULL&&lq->rear==NULL) /*空队*/ DataType GetHead(LinkQueue*lq,DataType x) { if(lq->front==NULL&&lq->rear==NULL) /*空队*/ return 0; x=lq->front->data; return x; }

(5)判断队空运算算法 int QueueEmpty(LinkQueue *lq) { return 1; else return 0; } if(lq->front==NULL&&lq->rear==NULL) return 1; else return 0; }

3.2.3 循环队列 1.队列的顺序存储结构为顺序队列。 MAXSIZE-1 … 2 1 rear front

a)空队 b)a、b入队 c)a、b出队,c、d入队 d)假溢出 rear 5 4 3 2 1 5 4 3 2 1 5 4 3 2 1 5 4 3 2 1 f e rear front d c rear front b a rear front front a)空队 b)a、b入队 c)a、b出队,c、d入队 d)假溢出

rear e4 e3 循环队列的类型定义: #define MAXSIZE 100 /*最大队列长度 */ typedef struct { datatype data[MAXSIZE]; /*存储队列的数据空间*/ int front; /*队头指针,指向队头元素*/ int rear; /*队尾指针,指向队尾元素的下一个位置*/ }SeqQueue; rear 3 e4 1 2 e3 front

e5 e6 e4 2.循环队列的特点 rear 1 2 3 3 e4 1 2 e3 将头尾连接成一个环,形成循环队列。 3 1 2 e3 (1)一般情况 rear front 2.循环队列的特点 rear 1 2 3 rear=front 3 e4 1 2 e3 front front (3) 队空 rear 将头尾连接成一个环,形成循环队列。 rear=front e5 e6 e4 3 1 2 e3 (2) 队满

若(rear+1)%maxsize=front, 称为队满。 5 4 3 2 1 5 4 3 2 1 5 4 3 2 1 rear f e d c d c front front rear rear g front (a)正常情况 (b) 队满 (c) 队空 若front=rear ,称为队空; 若(rear+1)%maxsize=front, 称为队满。

3.循环队列的基本操作 (1)构造空队列 SeqQueue *InitQueue() { SeqQueue *q; q=(SeqQueue*)malloc(sizeof(SeqQueue));/*开辟一个足够大的存储队列空间*/ q->front=q->rear=0; /*将队列头尾指针置为零*/ return q;}

(2)判断队空 int QueueEmpty(SeqQueue *q) { return(q->front==q->rear); /*如果队列为空,则返回1,否则返回0*/ }

int EnQueue(SeqQueue*q,datatype x) (3)入队 int EnQueue(SeqQueue*q,datatype x) { if((q->rear+1)%MAXSIZE==q->front) /*判断队列是否满*/ { printf("\n循环队列满!”); return FALSE; /* 若队列满,则终止*/ } q->data[q->rear]=x; /*将元素x入队*/ q->rear=(q->rear+1)%MAXSIZE; /*修改队尾指针*/ return TRUE;}

(4)出队 datatype DeQueue(SeqQueue *q) { datatype x; if(q->front==q->rear) {printf("\n循环队列空!不能做删除操作!"); return FALSE; } x=q->data[q->front]; q->front=(q->front+1)%MAXSIZE; /*修改队列头指针*/ return x; /*将被删除元素返回*/ }

3.3 应用 3.3.1栈的应用 【例3.1】 设计一个算法,判断一个表达式中符号“(”与“)”、“[”与“]”、“{”与“}”是否匹配。若匹配,返回1;否则返回0。

case ')':if(exps[top]=='(')top--; else nomatch=l ; break; case ']':if(exps[top]==’[’)top--; else nomatch=1 ; case '}':if(exps[top]== ’{‘)top--; else nomatch=l; } i++; if(nomatch==0&&top==-1) /*栈空且符号匹配则返回l*/ return 1; else return 0 ; /*否则返回0*/} #define Max 100 int match(char *exps) {char st[Max]; int top=-1,i=0; int nomatch=0; while(exps[i]!=’\0'&&nomatch==0) {switch(exps[i]) {case '(': top++;st[top]=exps[i] ;break; case '[': top++;st[top]=exps[i] ;break; case '{': top++;st[top]=exps[i] ;break;

【例3.2】数制转换问题。把非负十进制整数转换成n(2≤n≤35)进制数,各位系数如果大于9依次用大写英文字母A~Z表示。 (83)10=(123)8

while(x) /*除n取余,余数保存栈中*/ { Push(stack,x%n); x/=n;} main() { int x,n; do { scanf("%d",&x); scanf("%d",&n); }while(n<2 || n>35 || x<0); /*输入有效数据*/ while(x) /*除n取余,余数保存栈中*/ { Push(stack,x%n); x/=n;} while(!ISEmpty(stack)) /*出栈,直到栈空*/ { Pop(stack,x); if(x<10) printf("%c",x+'0'); /*输出’0’~’9’*/ else printf("%c",x+'A'-10); } }

【例3.3】利用一个栈逆置一个带头结点的单链表,已知head是带头结点的单链表(a1,a2,…,an) (其中n≥0)。 typedef struct node { datatype data; struct node *next; }linklist; linklist *head;

解题思路: 1)建立一个带头结点的单链表head。 2)输出该单链表。 3)建立一个空栈s(顺序栈)。 4)依次将单链表的数据入栈。 5)依次将单链表的数据出栈,并逐个存入单链表的数据域 。 6)再输出单链表。

main() { linklist *head; head=creatlist(); print(head); head=backlinklist(head); print(head);}

void print(linklist *head) /*输出单链表*/ { linklist *p; p=head->next; struct seqstack /*定义顺序栈*/ { datatype d[maxsize]; int top; }s; linklist *creatlist() /*建立单链表 */ { linklist *p,*q; p=q=(struct node *)malloc(sizeof(linklist)); head=p; p->next=0; p=(struct node *)malloc(sizeof(linklist)); scanf("%d",&p->data); while(p->data!=-1) { q->next=p; q=p; p=(struct node *)malloc(sizeof(linklist)); scanf("%d",&p->data); } q->next=0; return(head);} void print(linklist *head) /*输出单链表*/ { linklist *p; p=head->next; if(p==0) printf("empty 1ist." ); else {do {printf("%6d",p->data); p=p->next; } while(p!=0);} }

datatype pop(seqstack *s) /*出栈*/ { datatype y; if((*s).top==-1) {printf("栈为空"); return 0;} else {y=(*s).d[(*s).top]; (*s).top--; /*栈顶指针下移*/ return y; } } seqstack initstack() /*构造一个空栈s*/ { s.top=-1; return s; } int push(seqstack *s,datatype x) /*入栈*/ {if((*s).top==maxsize-1) { printf("栈已满"); return 0; } else {(*s).top++; (*s).d[(*s).top]=x; return x; } }

linklist *backlinklist(linklist *head)/*利用顺序栈s逆置单链表head*/ { linklist *p; p=head->next; initstack(); while(p) { push(&s,p->data); /*数据依次入栈s*/ p=p->next; } while(!stackempty(s)) { p->data=pop(&s); /*数据出栈依次存入单链表*/ p=p->next; } return(head);}

3.3.2队列的应用 【例3.4】打印杨辉三角形。

分析第 i 行元素与第 i+1行元素的关系 目的是从前一行的数据计算下一行的数据

从第 i 行数据计算并存放第 i+1 行数据

EnQueue(SeqQueue *q,datatype x) DeQueue(SeqQueue *q) {if(q->front==q->rear) {printf(“空队列!");exit(1);} x=q->data[q->front]; q->front=(q>front+1)% MAXSIZE; return x;} int GetHead(SeqQueue *q) { int e; if(q->front==q->rear) e=0; else e=q->data[q->front]; return e;} EnQueue(SeqQueue *q,datatype x) { if((q>rear+1)%MAXSIZE==q->front) {printf("\n队列是满的!"); exit(1);} q->data[q->rear]=x; q->rear=(q>rear+1)% MAXSIZE; }

void YangHui(int n) /*打印*/ { int j,s,t; EnQueue(q,0); /*添加行分隔符*/ EnQueue(q,1);EnQueue(q,1); /*第一行的值入队*/ for(j=2;j<=n;j++) {EnQueue(q,0); /*行分隔符0入队*/ do /*输出第j行计算第j+1行*/ { s=DeQueue(q); /*删除队头元素*/ t=GetHead(q); /*取队头元素*/ if(t) printf("%5d",t); else printf("\n"); /*否则输出一个换行符*/ EnQueue(q,s+t); /*第j+1行的对应元素s+t入队*/ }while(t!=0);} main() { YangHui(10);}

实例扩展 在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头各出一人配成舞伴。如两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。请编写程序,列出进入舞池的成员。

结 束!