C实现栈和队列
这两天再学习了数据结构的栈和队列,思想很简单,可能是学习PHP那会没有直接使用栈和队列,写的太少,所以用具体代码实现的时候出现了各种错误,感觉还是C语言功底不行。栈和队列不论在面试中还是笔试中都很重要,下面就介绍一下这两天栈和队列的学习经验
一:栈的学习
基础东西:栈是在表尾进行插入和删除的线性表,由此可知表尾是栈顶,表头为栈底,没有任何元素的栈是空栈。根据栈的结构可以知道:栈修改是按后进先出的原则进行的(LIFO),基本操作有插入、删除、初始化、取栈顶元素,判断是否是空栈等等。
栈的表示和实现:和上一节介绍过的线性表相似栈有两种表示方法(顺序表示和链式表示)因为和线性表类似(特殊的线性表)我只介绍顺序栈的就可以了。
顺序栈:利用一组连续的地址来依次存储栈的各个元素(从栈底到栈顶),用top指针指示栈顶元素,base指针指示栈底元素,所以top=base可以作为空栈的判断。插入一个元素top++,出栈一个元素top--,所以非空栈的指针始终在栈顶元素的下一个位置
顺序栈的结构体表示:
- //栈的顺序存储表示
- typedef struct{
- SElemType *base;//在栈构造之前和销毁后值是NULL
- SElemType *top;
- int stacksize; //已分配的存储空间
- }SqStack;
下面是我练习的代码,实现了栈的定义、栈的初始化、进栈操作、出栈操作、得到栈顶元素、遍历栈。需要注意的是出栈操作和得到栈顶元素的操作是有区别的,希望对大家栈的学习和回顾有所帮助。代码都是自己练习过的,可以直接运行
- /**
- * 栈
- * @author:zhaoyafei
- * @time:2015-6-16
- */
- #include <stdio.h>
- #include <stdlib.h>
- //预定义常量
- #define OK 1
- #define OVERFLOW -2
- #define ERROR 0
- #define STACK_INIT_SIZE 100 //存储空间的初始分配量
- #define STACKINCREMENT 10 //存储空间的分配增量stackincrement
- typedef int SElemType;
- //栈的顺序存储表示
- typedef struct{
- SElemType *base;//在栈构造之前和销毁后值是NULL
- SElemType *top;
- int stacksize; //已分配的存储空间
- }SqStack;
- //栈的初始化操作
- int InitStack(SqStack &S){
- S.base = (int *)malloc(STACK_INIT_SIZE * sizeof(SqStack));
- if(!S.base){
- exit(OVERFLOW);//分配空间失败
- }
- S.top = S.base;
- S.stacksize = STACK_INIT_SIZE;
- return OK;
- }
- //进栈操作
- int Push(SqStack &S, int e){
- if(S.top - S.base >= S.stacksize){//栈空间已经满
- S.base = (int *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SqStack));
- if(!S.base){
- exit(OVERFLOW);//分配失败
- }
- S.top = S.base + S.stacksize;
- S.stacksize += STACKINCREMENT;
- }
- *S.top++ = e;
- return OK;
- }
- //出栈
- int Pop(SqStack &S,int &e){
- if(S.top != S.base){
- e = * --S.top;
- return OK;
- }else{
- exit(OVERFLOW);
- }
- }
- //得到顶部元素
- void GetElem(SqStack S, int &e){
- if(S.top != S.base){
- e = * (S.top - );
- }else{
- exit(OVERFLOW);
- }
- }
- //打印出栈各个元素
- void PrintfStack(SqStack S){
- while(*(S.top-) && S.top != S.base){//证明不是空栈,且有值
- S.top = S.top - ;
- printf("%d ",*S.top);
- }
- printf("\n");
- }
- int main(){
- int e,i;
- int TextData[] = {,,,,,};
- SqStack Sa,Sb;
- InitStack(Sa);//初始化栈Sa;
- for(i = ; i < ; i++){
- Push(Sa,TextData[i]);
- }
- printf("**************栈基本操作*************\n");
- //初始化数据
- printf("初始化后的Sa:");
- PrintfStack(Sa);
- //得到栈顶元素
- GetElem(Sa,e);
- printf("Sa栈顶元素是:%d\n",e);
- //初始化数据
- printf("顶部出栈后Sa:");
- Pop(Sa,e);
- PrintfStack(Sa);
- }
二:队列的学习:
队列和栈相反,是一种先进先出(FIFO)的线性表,只能在一端进行插入,一端进行删除
基础:在队列中,进行出入的一端称作队尾,允许删除的一端称作队首。和线性表差不多可以用顺序和链式表示。
双端队列:双端队列是限定插入和删除的操作在表的两端进行的线性表,用的不是很多。
循环队列:百度上解释:”将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量“,其实就是把队列首尾相连,但是要有一定的要求,不是想怎么连就怎么连。
下面给出链表的结构体:
- //单链队列
- typedef struct QNode{
- QElemType data;
- struct QNode *next;
- }QNode, *QueuePtr;
- typedef struct{
- QueuePtr front;
- QueuePtr rear;
- }LinkQueue;
- //循环队列
- typedef struct{
- QElemType *base;
- int front;
- int rear;
- }SqQueue;
下面这段代码练习了队列的基本操作:队列结构体定义(比栈的稍微复杂一点)、在队尾插入新元素、删除队头元素、销毁队列、打印队列、循环队列的定义等等,这部分牵涉到好多的指针操作,如果有些困难可以在纸上划出队列的结构,列出指针的操作前后变化,就容易多了(个人感觉如果线性表学好了,这些操作根本不在话下)。需要注意循环队列操作中取余操作:(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
废话不多说,下面直接给出具体实现的代码:
- #include <stdio.h>
- #include <stdlib.h>
- //头文件
- #define ERROR -1
- #define OK 2;
- #define TRUE 1;
- #define OVERFLOW -2;
- //最大队列长度
- #define MAXQSIZE 100
- typedef int Status;
- typedef int QElemType;
- //单链队列
- typedef struct QNode{
- QElemType data;
- struct QNode *next;
- }QNode, *QueuePtr;
- typedef struct{
- QueuePtr front;
- QueuePtr rear;
- }LinkQueue;
- //循环队列
- typedef struct{
- QElemType *base;
- int front;
- int rear;
- }SqQueue;
- //********************************队列的基本操作*****************************
- //初始化队列
- Status InitQueue(LinkQueue &Q){
- Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));//动态分配空间
- if(!Q.front){
- exit(ERROR);//分配空间失败
- }
- Q.front->next = NULL;
- return OK;
- }
- //在队尾插入新元素
- Status EnQueue(LinkQueue &Q, int e){
- QueuePtr p;
- p = (QueuePtr)malloc(sizeof(QNode));
- if(!p){
- exit(ERROR);//分配失败
- }
- p->data = e;
- p->next = NULL;
- Q.rear->next = p;
- Q.rear = p;
- return OK;
- }
- void DestroyQueue(LinkQueue &Q){
- if(Q.front != Q.rear){
- while(Q.front){
- Q.rear = Q.front->next;
- free(Q.front);
- Q.front = Q.rear;
- }
- }
- }
- //删除队头元素,并用e返回
- Status DeQueue(LinkQueue &Q, int &e){
- if(Q.front != Q.rear){//先判断队列是否为空
- QueuePtr p;
- e = Q.front->next->data;
- if(Q.front->next == Q.rear){//队列只有一个元素
- p = Q.rear;
- Q.rear = Q.front;
- Q.front->next = NULL;
- }else{
- p = Q.front->next;
- Q.front->next = p->next;
- p->next = NULL;
- }
- free(p);
- return OK;
- }
- }
- //打印队列元素
- void PrintQueue(LinkQueue Q){
- if(Q.front != Q.rear){
- do{
- Q.front = Q.front->next;
- printf("%d ",Q.front->data);
- }while(Q.front->next);
- }
- printf("\n");
- }
- //********************************循环队列的基本操作*****************************
- //初始化队列
- Status InitQueueXh(SqQueue &Q){
- Q.base = (int *)malloc(MAXQSIZE * sizeof(int));//动态分配空间
- if(!Q.base){
- exit(ERROR);//分配空间失败
- }
- Q.front = Q.rear = ;
- return OK;
- }
- //在队尾插入新元素
- Status EnQueueXh(SqQueue &Q, int e){
- if((Q.rear + ) % MAXQSIZE == Q.front){
- exit(ERROR);//队循环列已满
- }
- Q.base[Q.rear] = e;
- Q.rear = (Q.rear + ) % MAXQSIZE;
- return OK;
- }
- int DestroyQueueXh(SqQueue &Q){
- return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
- }
- //删除队头元素,并用e返回
- Status DeQueueXh(SqQueue &Q, int &e){
- if(Q.front == Q.rear){//先判断队列是否为空
- return false;
- }
- e = Q.base[Q.front];
- Q.front = (Q.front + ) % MAXQSIZE;
- return OK;
- }
- //打印队列元素
- void PrintQueueXh(SqQueue Q){
- if(Q.front != Q.rear){
- do{
- printf("%d ",Q.base[Q.front]);
- Q.front++;
- }while(Q.front != Q.rear);
- }
- printf("\n");
- }
- //主方法
- int main(){
- int e, i;
- int Data[] = {,,,,,};
- printf("****************队列的基本操作**************\n");
- //初始化队列
- LinkQueue Qa, Qb;
- InitQueue(Qa);
- //初始化Qa
- for(i = ; i < ; i++){
- EnQueue(Qa,Data[i]);
- }
- //打印Qa
- printf("Qa的各个元素:");
- PrintQueue(Qa);
- //删除队首元素
- DeQueue(Qa,e);
- printf("删除Qa的队首元素:%d\n",e);
- printf("删除首元素后的Qa: ");
- PrintQueue(Qa);
- printf("销毁后的Qa: ");
- DestroyQueue(Qa);
- PrintQueue(Qa);
- printf("**************循环队列的基本操作************\n");
- //初始化队列
- SqQueue QaXh, QbXh;
- InitQueueXh(QaXh);
- //初始化Qa
- for(i = ; i < ; i++){
- EnQueueXh(QaXh,Data[i]);
- }
- //打印Qa
- printf("QaXh的各个元素:");
- PrintQueueXh(QaXh);
- //删除队首元素
- DeQueueXh(QaXh,e);
- printf("删除QaXh的队首元素:%d\n",e);
- printf("删除首元素后的QaXh: ");
- PrintQueueXh(QaXh);
- printf("得到QaXh的元素个数:%d\n",DestroyQueueXh(QaXh));
- }
C实现栈和队列的更多相关文章
- 学习javascript数据结构(一)——栈和队列
前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...
- [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)
再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...
- 剑指Offer面试题:6.用两个栈实现队列
一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...
- JavaScript数组模拟栈和队列
*栈和队列:js中没有真正的栈和队列的类型 一切都是用数组对象模拟的 栈:只能从一端进出的数组,另一端封闭 FILO 何时使用:今后只要仅希望数组只能从一端进 ...
- 用JS描述的数据结构及算法表示——栈和队列(基础版)
前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里 ...
- JavaScript中的算法之美——栈、队列、表
序 最近花了比较多的时间来学习前端的知识,在这个期间也看到了很多的优秀的文章,其中Aaron可能在这个算法方面算是我的启蒙,在此衷心感谢Aaron的付出和奉献,同时自己也会坚定的走前人这种无私奉献的分 ...
- Java数据结构和算法之栈与队列
二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为 ...
- python数据结构之栈、队列的实现
这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...
- 栈和队列的面试题Java实现【重要】
栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...
随机推荐
- 关于c++类的内存分配
参考:这里 虽然有些地方错了,但是也可以一看,大概能加深对c++类相关的内存分配的了解 然后这还不算十分深入,更深入的可以看这里. 这本书是时候读一下了:<深度探索C++对象模型> (待续 ...
- 使用属性动画 — Property Animation
属性动画,就是通过控制对象中的属性值产生的动画.属性动画是目前最高级的2D动画系统. 在API Level 11中添加.Property Animation号称能控制一切对象的动画,包括可见的和不可见 ...
- sublime text3下BracketHighlighter的配置方法
st3的配置方法和st2是有区别的,所以网上搜索到的方法大多不能用,我google之后总结了一下. 一. 1.在st3中按preferences-->package settings--> ...
- Ceph RGW 的 OSPF负载均衡 + quagga的配置
随着开源技术的发展,以及商业设备价格的不断攀升.大公司总是希望能使用开源的方案来替换过去使用的商业设备.比如之前大家用的很多的F5和A10,现在已经在逐步被LVS替换.传统的单个lvs的性能是比不 ...
- 【bzoj4517】 Sdoi2016—排列计数
http://www.lydsy.com/JudgeOnline/problem.php?id=4517 (题目链接) 题意 求n个数中正好m个数位置不变的排列数. Solution $${错排公式: ...
- a版本冲刺第一天
队名:Aruba 队员: 黄辉昌 李陈辉 林炳锋 鄢继仁 张秀锋 章 鼎 学号 昨天完成的任务 今天做的任务 明天要做的任务 困难点 体会 408 学习测试文档的编写 继续学习并借鉴,开始着手写 ...
- 刚开始用git遇到的无法提交变更的问题
原来我在目录里打开命令行,git bash默认执行的目录是c:/users了,错误的使用了git init,把$HOME 路径下的所有文件载入 git 仓库了,删除$HOME 路径下的".g ...
- <<< javascript地址栏,代码
不伤及服务器,可以用来测试项目效果 修改网页.不修改服务器端任何网页页面 javascript:document.body.contentEditable='true';document.design ...
- infragistics-webdatagrid
infragistics-webdatagrid DataRow DataTable DataSet DataColumn stringBuilder append appendFormat 存储过程 ...
- 数据库性能优化常用sql脚本总结
最近闲来无事,正好抽出时间,来总结总结 sql性能优化方面的一下小技巧,小工具.虽然都是些很杂的东西,但是我个人觉得,如果真的清楚了里面的一下指标,或许真的能抵半个DBA. 有些时候,找不到DBA或者 ...