数据结构 栈与队列的实现

基础结构

typedef int STDataType; typedef struct Stack
{
    
    
STDataType* _a;
int top; // 栈顶 
int capacity; // 容量
}Stack;

申请空间

void ListCapacity(Stack*ps)
{
    
    
    if(ps->top==ps->capacity)
    {
    
    
        int newcapacity=ps->capacity==0?4:ps->capacity*2;

        STDataType*ptr=(STDataType*)realloc(ps->data,sizeof(STDataType)*newcapacity);
        if(ptr==NULL)
        {
    
    
            perror("ptr:");
            exit(-1);
        }
        ps->capacity=newcapacity;
        ps->data=ptr;
    }
}

入栈

这儿就是顺序表尾插

  1. 判断容量
  2. 增容
  3. 栈顶++
void StackPush(Stack* ps, STDataType data)//入栈
{
    
    
    ListCapacity(ps);
    ps->data[ps->top]=data;
    ps->top++;

}

出栈

  • 一定要判空哟,不让就出大问题了,栈顶变成了负数,变成负数那怎么访问下标
  • 就像喝奶茶用筷子一样难受
void StackPop(Stack* ps)// 出栈
{
    
    
    assert(!StackEmpty(ps));
    ps->top--;
}

取栈顶元素

  • top是顺序表的尾巴,也是栈的顶部,所以栈顶元素就是top这个位置的数据
STDataType StackTop(Stack* ps)
{
    
    
    return ps->data[ps->top];
}

判空

  • 每次增容栈顶都会更新,跑到新入栈的数据上面,没有数据就代表栈是空的
int StackEmpty(Stack* ps)// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
{
    
    
    return ps->top==0;
}

销毁

  • 动态开辟的内存一定要释放,不让造成内存泄露,如果代码长一直不释放就会越来越卡
  • 就像你开机就有好多app占用能的运行内存
void StackDestroy(Stack* ps)
{
    
    
    free(ps->data);
    ps->data=NULL;
    ps->top=0;
    ps->capacity=0;
}

基础结构

链表结构

typedef struct QListNode 
{
    
     
	struct QListNode* _next; 
	QDataType _data; 
}QNode; 

队列结构

typedef struct Queue
{
    
    
    QNode* front;//头
    QNode* rear;//尾
}Queue;

分共明确,需要哪里就调用那个指针,节省时间且增加效率(后文实现),且这是一种新的方法可以实现

  1. 传二级指针
  2. 创头节点
  3. 返回值
  4. 在传一个结构体(多种不同作用的指针)

入队列

void QueuePush(Queue* q, QDataType data)
{
    
    
    QNode*newnode=(QNode*)malloc(sizeof(QNode));
    newnode->data=data;
    if(QueueEmpty(q))
    {
    
    
        q->front=q->rear=newnode;
    }
    else
    {
    
    
        q->rear->next=newnode;
        q->rear=q->rear->next;
    }
}

出队列

  • 存下一个节点,在链接即可
void QueuePop(Queue* q)
{
    
    
    QNode*next =q->front->next;
    free(q->front);
    q->front=next;
}

取队头

  • front为队列的头,也是链表的头,所以取这个队头操作小菜一碟
int QueueEmpty(Queue* q)
{
    
    
    return q->front==NULL&&q->rear==NULL&&q->front==q->rear;
}

队列元素个数

  • 这里判断条件一定不能为空(此逻辑),位空的话插入新节点置为NULL即可
int QueueSize(Queue* q)
{
    
    
    int count =0;
    QNode* cur=q->front;
    while(cur!=q->rear->next)
    {
    
    
        count++;
        cur= cur->next;
    }
    return count;
}

取队尾

  • 队尾一直是是背rear指向的,每次查入rear都要跌代(小菜一碟)
QDataType QueueBack(Queue* q)
{
    
    
    assert(!QueueEmpty(q));
    return q->rear->data;
}

销毁队列

void QueueDestroy(Queue* q)
{
    
    
    QNode*cur=q->front;
    while(cur!=q->rear->next)
    {
    
    
        QNode*next=cur->next;
        free(cur);
        cur=next;
    }
    q->front=NULL;
    q->rear=NULL;
}

他们其实就是可以看出顺序表与链表的一种变种


如果看到错误请直接在评论留言哪里可以优化或者有更好的方法请直接和我私信,你的指错让我和你变得更加的优秀,如果文章帮到你了,那么请给我点个赞谢谢

猜你喜欢

转载自blog.csdn.net/Legwhite/article/details/119780349