C语言实现数据结构——栈和队列

栈的定义:
栈就像一个货板,增加和取出都只能在尾部进行
栈的ADT
ADT 栈 stack
Data:
	同线性表。数据元素为零个或者有限个,中间元素只有一个前驱一个后驱,首元素只有后驱;尾元素只有前驱
Opration:
	InitStack(*s);  初始化一个空栈
	Push(*s,e);    栈的元素插入,入栈,值为e
	Pop(*s,*e);     栈元素的删除,出站,e返回值
	ClearStack(*s);      清空栈
	StackLength(s);      栈的元素个数
	DestroyStack1(*s);    栈存在,则销毁
	GetTop(*s,*e);            返回栈顶元素
	IsEmptyStack(s)            判断栈是否为空
endADT
栈的顺序存储结构
栈是一种特殊的线性表,线性表的存储结构使用数组,顺序存储结构需要有三个元素:maxsize、data、length;顺序栈也需要这样的元素
typedef struct
{
	SElem data[MAXSIZE];
	int top;
}SqStack;
入栈操作:
1.top++
2.赋值
status Push(SqStack *s,SElem e)
{
	if (s->top==MAXSIZE-1)
		return ERROR;
	s->top++;
	s->data[s->top]=e;
	return OK;
}
出栈操作:
1.top--
2.赋值
status Pop(SqStack *s,SElem *e)
{
	if (s->top==-1)   //判断是否为空栈
		return ERROR;
	*e=s->data[s->top];
	s->top--;
	return OK;
}
两栈共享空间
typedef struct
{
    SElem data[MAXSIZE];
    int top1;
    int top2;
}sqDStack;
//栈的空间共享的实现-入栈
status PushDStack(sqDStack *s,SElem e,int stackNumber)
{
    if (s->top1+1==s->top2)
    {
        return ERROR;
    }
    if (stackNumber=1)  //往栈一入
    {
        s->top1++;
        s->data[s->top1]=e;
    }
    else if (stackNumber=2)
    {
        s->top2++;
        s->data[s->top2]=e;
    }
    return OK;
}
栈的链式存储结构
说明:栈的链式存储是线性表的链式存储的一种特殊结构;栈中只有栈顶进行插入和删除,因此比普通的单链表简单;由于栈顶有头指针,而链表也有头指针,因此可以考虑将链表的头作为栈顶,这样链表的头指针便可作为栈的头指针;头结点便不需要了,因为有栈顶指针。
//链栈的结点
typedef struct stackNode
{
    SElem data;
    struct stackNode *next;
}stackNode,*LinkStackPtr;   //指向结点指针
//链栈的结构
typedef struct LinkStack
{
    LinkStackPtr top;     //头指针为栈顶指针
    int count;
}LinkStack;

入栈操作:
1.先将新结点s->next指向栈顶结点
2.再将栈顶结点移动至s

status PushLinkStack(LinkStack *ls,SElem e)
{
    LinkStackPtr s = (LinkStackPtr)malloc(sizeof(stackNode));  //新建一个结点
    s->data=e;
    s->next=ls->top;   //先将s->next指向栈顶结点
    ls->top=s;         //在将栈顶结点移动至s
    ls->count++;
    return OK;
}
出栈操作:
1.先将栈顶元素赋值给e
2.再将栈顶元素向下移动
//链栈的出栈操作
status PopLinkStack(LinkStack *ls,SElem *e)
{
    LinkStackPtr s =ls->top;
    *e = s->data;
    ls->top=s->next;
    ls->count--;
    return OK;
}

栈的应用
递归:后续补充


四则运算:后续补充
队列
队列的定义
街边新开了一家奶茶店,人太多只能排队取餐;新来的人排在后面,先到的人先买到奶茶;所有的人形成一个队列,遵循先进先出的原则;
队列的ADT
/*
ADT 队列 queue
    Data:
        同线性表
    Operation:
        IniteQueue(*Q);   //初始化一个队列
        ClearQueue(*Q);   //清空队列的元素
        DestroyQueue(Q);  //销毁队列
        IsEmptyQueue(Q);  //判断队列是否为空
        GetHeadQueue(*Q,e);   //获取头元素,返回给e
        AddQueue(*Q,e);   //将e插入队尾
        DeleteQueue(*Q,*e);   //删除队列的头,相当于出队
        LengthQueue(*Q);     //获取队列的长度
endADT
*/
队列的顺序存储结构
队列的顺序存储结构与线性表一致,按照以往的存储方式,出队时所有的位置都要变化,为此,可以使用循环队列,循环队列就是出队后其他位置不变化,循环队列设置front表示队头,设置rear表示队尾的下个位置;满队的条件:(rear+1)%maxsize=front;长度公式为:(rear-front+maxsize)%maxsize
//循环队列的顺序存储结构
typedef int QElem;
typedef struct
{
    QElem data[MAXSIZE];
    int front;      //队头的位置
    int rear;       //队尾的下一位置
}SqQueue;
队列顺序存储的操作
入队、出队、长度
//初始化空循环队列
status InitQueue(SqQueue *q)
{
    q->front=0;
    q->rear=0;
    return OK;
}

//循环队列的入队,将队列元素e插入队尾
status AddQueue(SqQueue *q,QElem e)
{
    //判断是否队满
    if (q->front==(q->rear+1)%MAXSIZE)
    {
        return ERROR;
    }
    q->data[q->rear]=e;
    q->rear=(q->rear+1)%MAXSIZE;   //rear指向下个位置,如果满了则从头开始
    return OK;
}

//循环队列的长度
int LengthQueue(SqQueue *q)
{
    return (q->rear-q->front+MAXSIZE)%MAXSIZE;
}

//循环队列的出队,将队首元素删除,并赋值给e
status DeleteQueue(SqQueue *q,QElem *e)
{
    //判断队列为空
    if (q->front==q->rear)
    {
        return ERROR;
    }
    *e = q->data[q->front];
    q->front = (q->front+1)%MAXSIZE;  //front向后移动,若为对尾,则向头移动
    return OK;
}

//循环队列打印
status PrintQueue(SqQueue *q)
{
    if (q->front==q->rear)
    {
        return ERROR;
    }
    int flag = q->front;   //记录起始位置
    for(int i=0;i<LengthQueue(q);i++)
    {

        printf("%d ",q->data[flag]);
        flag =(flag+1)%MAXSIZE;
    }
}
队列的链式存储
结构:队头指针指向头结点,队尾指针指向终端结点
//链队列的实现
typedef struct QNode
{
    QElem data;
    struct QNode *next;
}QNode, *QueuePtr;
//队头指针指向头结点,对尾指针指向终端结点
typedef struct
{
    QueuePtr front,rear;   //队头、队尾指针
}LinkQueue;
//链队的存储结构=入队
status AddLinkQueue(LinkQueue *q,QElem e)
{
    QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
    if (!s)
    {
        exit(OVERFLOW);   //溢出
    }
    s->data=e;
    s->next=NULL;  //新结点赋值
    q->rear->next=s;  //1队尾结点的next指向新结点
    q->rear=s;    //2队尾rear指向s
    return OK;
}

//链队的存储结构-出队
status  DeleteLinkQueue(LinkQueue *q,QElem e)
{
    QueuePtr p;
    if (q->front==q->rear)
    {
        return ERROR;
    }
    p=q->front->next;  //p为对首后面的链表
    e=p->data;    //队首元素赋值给e
    q->front->next=p->next;  //1头指针指向队首后面的结点
    if (q->rear==p)         //只有一个元素的情况
    {
        q->rear=q->front;   //尾指针指向头结点
    }
    free(p);
    return OK;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值