360 likes | 530 Views
数据结构. C 语言版. 内 容 3.1 栈的概念 3.2 栈的存储结构 3.3 顺序栈的操作算法 3.4 链栈的操作算法 3.5 栈的应用举例 --- 表达式求值 3.6 队列的概念 3.7 队列的存储结构 3.8 循环队列的操作算法 3.9 链队的操作算法. 第三章 : 栈和队列. 3.1 栈的概念 1. 定义: 栈 (Stack) 是限定仅在表的一端进行插入或删除操作的线性表。 2. 栈的示意图 P44 3. 栈的抽象数据类型定义 P45. 3.2 栈的存储结构。 有两种存储结构 :.
E N D
数据结构 C语言版
内 容 • 3.1栈的概念 • 3.2栈的存储结构 • 3.3顺序栈的操作算法 • 3.4链栈的操作算法 • 3.5栈的应用举例---表达式求值 • 3.6队列的概念 • 3.7队列的存储结构 • 3.8循环队列的操作算法 • 3.9链队的操作算法
第三章:栈和队列 3.1栈的概念 1.定义: 栈(Stack) 是限定仅在表的一端进行插入或删除操作的线性表。 2.栈的示意图 P44 3.栈的抽象数据类型定义 P45
3.2栈的存储结构。 有两种存储结构:
顺序栈的类型定义: //-- -- --栈的顺序存储表示-- -- --#define STACK_NINT_SIZE 100;//存储空间初始分配量#define STACKINCREMENT 10; //存储空间分配增量typedef struct{SElemType *base; //在栈构造之前和销毁之后,base的值为NULLSElemType *top; //栈顶指针int stacksize; //当前已分配的存储空间,以元素为单位}SqStack
//-- -- --基本操作的函数原型说明-- -- --Status InitStack(SqStack &S);//构造一个空栈SStatus GetTop(SqStack S,SElemType &e);//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORStatus Push(SqStack &S,SElemType e);//插入元素e为新的栈顶元素Status Pop(SqStack &S,SElemType &e);//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
链栈的类型定义: typedef struct LNode{//结点类型ElemType data;struct LNode *next;}Lnode,*Linkstack;Linkstack S;
3.3顺序栈的操作算法 1建立一个空栈Status InitStack(SqStack &S){//构造一个空栈SS.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!S.base)exit(overflow); //存储分配失效S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}//InitStack
2.取栈顶元素Status GetTop(SqStack S,SElemType &e) //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORif(S.top==S.base) return ERROR;e=*(S.top-1);return OK;}//GetTop
3.压栈pushStatus Push(SqStack &S,SElemType e){//插入元素e为新的栈顶元素if(S.top-S.base>=S.stacksize){//栈满,追加存储空间S.base=(SElemType*)realloc(S.base,(S.stacksize+ STACKINCREMENT)*sizeof(SElemType));if(!S.base)exit(OVERFLOW);//存储分配失败S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}//push
4.出栈popstatus Pop(SqStack &S,SElemType &e){ //若栈不为空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERRORif(S.top==S.base)return ERROR;e=*--S.top;return OK;}//Pop
5 判断栈是否为空 int Empty(SqStack S){//若栈为空,则返回0,否则返回1if(s.top==s.base) return (0);else return (1);} 6 判断栈是否为满 int Full(SqStack S){//若栈为满,则返回0,否则返回1if(s.top-s.base)>=s.stacksize return (0);else return (1);}
思考:两个栈共享同一段内容空间,为了使得空间利用率最高,应如何分配栈空间?思考:两个栈共享同一段内容空间,为了使得空间利用率最高,应如何分配栈空间?
3.4链栈的操作算法 1.建立一个空栈 Status InitLStack (Linkstack &S){S=NULL;return ok;}//InitLStack
2.取栈顶元素 Status GettopLStack (Linkstack &S,SElemType &e){//若栈不为空,则用e返回S的栈顶元素,并返回OK,否则返回ERROR.if(S==NULL) return ERROR;e=S->data;return(OK);}//GettopLStack
3.压栈Push Status PushLStack(Linkstack &S,SElemType e){//插入元素e为新的栈顶元素Lnode *p;p=(Lnode *)malloc(sizeof(Lnode));p->data=e;p->next=S;S=p;}//PushLStack
4.出栈Pop Status PopLStack(Linkstack &S,SElemType &e){//若栈不为空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR if(s==NULL) return ERROR;e=S->data;S=S->link;return OK;}//PopLStack
5.判断栈是否为空 int link_empty(Linkstack &S){//若栈为空则返回1,否则返回0if(S==NULL) return(1);else retrun(0);}
3.5栈的应用举例---表达式求值 算法的基本思想是: (1)首先置操作数栈为空栈,表达式起始符“#”为运算符的栈底元素; (2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符,则和OPTR栈的栈顶运算符比较优符后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。 算法描述p53 *栈与递归的实现
3.6队列的概念 1、定义:队列是一种先进先出(FIFO:First In First Out)的线性表。它只允许在表的一端进行插入,而在另一端删除元素。 2、示意图
3、队列的抽象数据类型定义 队列的抽象数据类型定义: ADT Queue{ 数据对象:D={ai|ai∈ElemSet,i=1,2,...,n,n≥0} 数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n} 约定其中a1端为队列头,an为队列尾。 基本操作: InitQueue(&Q) 操作结果:构造一个空队列Q。 DestroyQueue(&Q) …… } ADT Queue p59
4、双端队列 a 定义:双端队列是限定插入和删除操作在表的两端进行的线性表。 b 双端队列的示意图
3.7队列的存储结构 ★有两种存储结构 ★顺序队列的示意图
3.8循环队列的操作算法 1、循环队列的基本思想: 在顺序队列中,头指针front始终指向队列头元素,而尾指针rear始终指向队列尾元素的下一个位置,随着进队、出队操作的进行,有可能会出rear指针已到达队列存储空间的终点,而队列的实际可用空间并未占满现象。为了避免这种现象的发生,一个巧妙的办法是将顺序队列臆造为一个环状空间,称之为循环队列。如图所示:
2、循环队列的队空队满条件 为了方便起见,约定:初始化建空队时,令front=rear=0,当队空时:front=rear当队满时:front=rear 亦成立因此只凭等式front=rear无法判断队空还是队满。有两种方法处理上述问题:(1)另设一个标志位以区别队列是空还是满。(2)少用一个元素空间,约定以“队列头指针front在队尾指针rear的下一个位置上”作为队列“满”状态的标志。即:队空时: front=rear队满时: (rear+1)%maxsize=front
3、循环队列的类型定义: //-- -- --循环队列---队列的顺序存储结构-- -- #define MAXQSIZE 100 //最大队列长度typedef struct{QELemType *base ; //初始化的动态分配存储空间int front; //头指针,若队列不空,指向队列头元素int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置}SqQueue;
4、建立空的循环队列的算法 Status InitQueue(SqQueue &Q){//构造一个空队列QQ.base=(QElemType *)malloc(MAXQSIZE *sizeof(QElemType));if(!Q.base)exit(WVERFLOW);//存储分配失败Q.front=Q.rear=0;return OK; }
5、求循环队列中元素的个数 int QueueLength(SqQueue Q){//返回Q的元素个数,即队列的长度return(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;} 6、进队算法 Status EnQueue(SqQueue &Q,QElemType e){//插入元素为Q的新的队尾元素if((Q.rear+1) % MAXQSIZE==Q.front)returnERROR;//队列满Q.base[Q.rear]=e;Q.rear=(Q.rear+1) % MAXQSIZE;return OK;}
7、出队算法 Status DeQueue(SqQueue &Q,QElemType &e){//若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERRORif(Q.front==Q.rear) return ERROR;e=Q.base[Q.front];Q.front=(Q.front+1)%MAXQSIZE;return OK;}
3、9链队的操作算法 1、链队的类型定义 //-- -- -单链队列---队列的链式存储结构-- --typedefstruct QNode {QElemType data;struct QNode *next;}QNode, *QueuePtr;typedefstruct {QueuePtr front;//队头指针QueuePtr rear;//队尾指针}LinkQueue;
2、建立空的链队 Status InitQueue(LinkQueue &Q){//构造一个空队列QQ.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(OVERFLOW);Q.front->next=NULL;return OK;}
3、进队算法 Status EnQueue(LinkQueue &Q,QElemType e){//插入元素e为Q的新的队尾元素p=(QueuePtr)malloc(sizeof(QNode));if(!p) exit(OVERFLOW);p->data=e; p->next=NULL;Q.rear->next=p;Q.rear=p;return OK;}
4、出队算法 Status DeQueue(LinkQueue &Q,QElemType &e){//若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERRORif(Q.front==Q.rear) return ERROR;p=Q.front->nxet;e=p->data;Q.front->next=p->next;if(Q.rear==p) Q.rear=Q.front;free(p);return OK;}