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 ...
随机推荐
- Sqlite创建增删改查
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- APiCloud真机调试需要注意的几个问题
具体请看官方文档:http://docs.apicloud.com/Dev-Tools/wifi-debug. APiCloud Android手机真机调试,需要首先在手机上安装官网提供的apploa ...
- 为自己的爬虫更换代理和HTML头部
import requestsimport reimport randomimport time class download(): def __init__(self): self.iplist = ...
- oracle---触发器总结
一.触发器简介 触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行.因此触发器不需要人为的去调用,也不能调用.然后,触发器的触发条件其实在你定义的时候就已经设定好了.这里面需 ...
- jQuery-3~4章
jQuery-3~5章 JQuery003-JQuery中的DOM操作 jQuery中的DOM操作: 1.查找节点 A.查找元素节点 B. 查找属性节点 var s1 = $("ul li: ...
- Web jquery表格组件 JQGrid 的使用 - 7.查询数据、编辑数据、删除数据
系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...
- C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用
1.直接调用 已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL.这个比较常见也很简单 即有完整的webservice文件目录如下图 ...
- tyvj1938 最优战舰
描述 太空战队顺利地完成了它的第一次使命,这一行动的受益者陆军本部当即决定,请陆军的战士们投票选出最优战舰并报司令总部进行表彰.为防止有人利用高科技手段造假,陆军本部决定使用最原始的方法进行投票.可不 ...
- tomcat乱码原因--基本的编码问题
tomcat乱码原因:在学习servlet时候,经常会遇到中文乱码的问题,网上查只知道如何设置不乱码,其中的原理不是很明白.我认为明白其中的原理,乱码问题就很容易解决 tomcat乱码解决方法: po ...
- 【html】学习记录-拖放(drag and drop)
目的:实现拖动目标并放置到指定区域. 使元素可拖动,涉及到元素的全局属性draggable <img draggable="true" /> 即img元素设置为可拖 ...