《算法导论》第十章——基本数据结构(一):栈与队列
来源:互联网 发布:中山淘宝招聘信息查询 编辑:程序博客网 时间:2024/06/06 00:24
引言:算法操作的集合可以随着时间的改变而增大,减小,或者产生其他变化,我们称这种集合是动态的。接下来的五章,我们将研究计算机上表示和操作有穷动态集合的一些基本技术。本文主要为你讲解栈与队列的操作和实现,建议将这些操作制作成库,方便以后的引用,避免重复编码。系列文章为算法导论的笔记和相关习题解答。
本文来源:栈与队列
动态集合的元素
元素包括两个部分:关键字+卫星数据
动态集合上的操作
主要包括两个大的方面:查询
我们约定:集合为S,关键字为k,指向元素的指针为x
Search(S,k)
Inserrt(S,x)
Delete(S,x)
Minimum(S)
Maximum( S )
Successor (S,x)
Predecessor(S,x)
栈和队列
一、栈
实现了一种先进先出的策略。通常情况下我们采用数组加栈顶指示top来实现,约定top==0(或者-1)的时候表示栈为空;同时如果stack的长度是m,那么要考虑元素个数超过m以后产生的溢出问题。栈的一些定义和基本操作如下:
#ifndef MAXSTACKSIZE#define MAXSTACKSIZE 200#endiftypedef int StackDataType;typedef struct mystack{ int top; StackDataType data[MAXSTACKSIZE];}Stack,*StackPointer;extern int IsEmpty(Stack s); extern int Push(StackPointer s, StackDataType element);extern StackDataType Pop(StackPointer s);
注明:stack的数据结构还可以定义一个指针和大小,来取代数组。这些操作的实现方式如下:
#include"stack.h"#include<stdlib.h>#include<stdio.h>StackDataType Pop(StackPointer s){ if(s->top==-1){ printf("the stack is already empty!\n"); exit(1); } --(s->top); return s->data[s->top+1];}int IsEmpty(Stack s){ if(s.top==-1){ return 1; } else{ return 0; }}int Push(StackPointer s,StackDataType element){ if(s->top >= MAXSTACKSIZE-1){ printf("the stack is over flow!\n"); return 0; } ++(s->top); s->data[s->top]=element; return 1;}
二、队列
我们可以把队列想象成排队等待服务的人群,同样也可以用 数组+对头指针+对尾指针 来实现队列这个数据结构;其中,head表示下一个要出列的元素,tail表示刚刚进入队列的元素。另外,为了实现环绕,我们需要把队列实现成为循环数组的模式,这个可以通过取模运算来实现。这样,head==tail+1表示队列已经满了;但是,此时我们会发现,如果我们让元素逐个出列,那么当最后一个元素出列的时候,同样满足head=tail+1;也就是说,队列在空和满的情况下具有相同的抽象条件。为了对此进行区分,我们用tail表示下一个进入队列的元素将要进入队列的位置,那么,初始化情况下,所以head=tail表示队列为空,初始情况下,head=tail=0;如果我们用head=tail+1表示队列为满的情况,意味着这个情况下,队列中有一个位置处于没有利用的状态,如果要利用这个元素,又会出现head=tail表示空和满两种情况。
关于队列的一些操作实例可以看下图,从而理解上面一段中的相关情况:
队列的一些定义的基本的操作如下:
#ifndef MAXQUEUESIZE#define MAXQUEUESIZE 200#endiftypedef int QueueDataType;typedef struct myqueue{ int tail; int head; QueueDataType data[MAXQUEUESIZE];}Queue,*QueuePointer;extern int IsEmpty(Queue queue);extern int IsFull(Queue queue);extern int EnQueue(QueuePointer queuep, QueueDataType element);extern QueueDataType DeQueue(QueuePointer queuep);
操作实现:
#include"queue.h"#include<stdlib.h>#include<stdio.h>/*make sure the queue is not empty when you delete element from it*/QueueDataType DeQueue(QueuePointer queue){ if(queue->head==queue->tail){ printf("the queue is already empty!\n"); exit(1); } QueueDataType temp; temp=queue->data[queue->head]; ++(queue->head); if(queue->head==MAXQUEUESIZE)// queue->head=0; return temp;}int IsEmpty(Queue queue){ if(queue.head==queue.tail){ return 1; } else{ return 0; }}int IsFull(Queue queue){ if(queue.head==(queue.tail+1)%MAXQUEUESIZE){ return 1; } else return 0;}int EnQueue(QueuePointer queue,QueueDataType element){ if(IsFull((*queue))){ printf("the queue is over flow!\n"); return 0; } queue->data[queue->tail]=element; ++(queue->tail); if(queue->tail==MAXQUEUESIZE) queue->tail=0; return 1;}
心得:栈与队列,分别是两种FIFO和FILO的数据结构,至于具体实现,栈的增长和队列进出的方向完全可以由用户定义。另外,在实际的编程中,以循环队列的实现为例,容易出现逻辑错误的地方在于条件判断和边界条件的设定。其中条件判断要是充要条件,也就是说,你的代码需要能准确反应你的文字表述的意图,虽然我们设定的条件是队列满,但是如果用head=tail,虽然表示了队列满的情况,但是它也表示队列是空的情况,所以是不正确的。比如判断队列是满还是空,如果我们想要将数组的每个元素都利用,这时就会发现队列在满和空的时候满足同样的条件head=tail,显然,这是应该避免的;所以浪费了一个空间,来区分队列是满还是空这个情况。经验:行动前周密的思考能大量节省时间。
练习:编程实现2,4,5,6,7:
2,一个栈stack1从低地址到高地址,另外一个栈stack2从高地址到低地址:当top1>=top2时,栈溢出。
4,解答:参见本文中的代码,里面有对溢出情况的处理
5,解答:参见代码biqueue.c
6,解答:两个栈,栈底相连就是一个队列,但是要注意这两个栈为空的边界条件。
7,解答:两个队列,参考下图
- 《算法导论》第十章——基本数据结构(一):栈与队列
- 算法导论第十章 基本数据结构实现(栈,队列,链表),课后题答案
- 算法导论第十章:基本数据结构
- 算法导论 第十章 基本数据结构
- 算法导论第十章基本数据结构
- 算法导论 第十章:基本数据结构
- 算法导论 第十章 基本数据结构
- 栈与队列_第10章_基本数据结构_算法导论
- [算法导论]第十章《栈和队列》
- MIT:算法导论——7.1.基本数据结构_栈、队列、链表、有根树
- 算法导论第十章-基本数据结构-Cpp代码实现
- 算法导论_第十章_基本数据结构
- 算法导论 第十章 基本数据结构 练习10.1-2
- 算法导论——栈与队列
- 【数据结构与算法001】基本数据结构——队列
- 数据结构与算法(14)——队列习题一
- 《算法导论》 — Chapter 10 基本数据结构
- 算法导论第10章-基本数据结构-10.1栈和队列
- unity3d学习笔记(八)--NGUI制作游戏界面
- 如何在多台机器上共享ios证书(转)
- 前端页面开发之Node.js初学者指南
- vc获取操作系统的语言
- java中集合类比较
- 《算法导论》第十章——基本数据结构(一):栈与队列
- 宏的一些使用
- WPF WindowState.Maximized 和 Normal
- weblogic encrypt clear text password
- AnyChat使用攻略之独立部署Linux视频服务器
- struts2零配置详解(struts-Convention-plugin)
- JAVA虚拟机加载类的三种方式
- 【ios游戏开发】之UDID和OpenUDID扫盲
- 如何自己编写Makefile