数据结构中的栈和队列-C语言版

1、数据结构概述

   栈和队列,也属于线性表,因为它们也都用于**存储逻辑关系为 "一对一"** 的数据,但由于它们比较特殊,因此将其单独作为一章,做重点讲解。

   使用栈结构存储数据,讲究“先进后出”,即最先进栈的数据,最后出栈;使用队列存储数据,讲究 "先进先出",即最先进队列的数据,也最先出队列。
   栈也可分为顺序栈和链表,队列也分为顺序队列和链队列, 也就是说,栈和队列都可以使用数组和链表两种线性结构来表示。

1.1 栈


常见的栈操作

  • push(x) – 元素 x 入栈 (时间复杂度O(1))
  • pop() – 移除栈顶元素 (时间复杂度O(1))
  • top() – 获取栈顶元素 (时间复杂度O(1))
  • empty() – 返回栈是否为空 (时间复杂度O(1))
    也就是说,栈这种数据结构的添加、删除操作的时间复杂度都是O(1)

顺序存储结构下的栈,自己实现的代码如下

typedef struct {
    int *data;		//栈中元素存放的地方
    int size;		//当前栈中有多少个元素
    int capacity;	//栈的最大深度
} MyStack;

MyStack *stackCreate(int capacity)
{
    MyStack *stack = (MyStack *)malloc(sizeof(MyStack));
    stack->data = (int *)malloc(sizeof(int)*capacity);
    stack->size = 0;
    stack->capacity = capacity;
    return stack;
}

void stackPush(MyStack *obj, int value)
{
    obj->data[obj->size] = value;
    obj->size++;
}

void stackPop(MyStack *obj)
{
    obj->size--;
}

bool stackEmpty(MyStack *obj)
{
    if(obj->size == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int stackTop(MyStack *obj)
{
    return obj->data[obj->size-1];
}

void stackfree(MyStack *obj)
{
    free(obj->data);
    free(obj);
}

链式存储结构下的栈,代码如下

1.2 队列


队列具有以下两个特点:

  • 数据从队列的一端进,另一端出;
  • 数据的入队和出队遵循"先进先出"的原则;

用C代码实现一个循环队列

typedef struct {
    int *data;	//队列中的数据
    int front;	//对头指针
    int rear;	//队尾指针
    int size;	//队列总长度
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue *obj = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
    obj->data = (int *)malloc(sizeof(int)*k);
    obj->front = -1;
    obj->rear = -1;
    obj->size = k;
    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    if(obj->front==-1 && obj->rear==-1)
    {
        return true;
    }
    return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    if( (obj->rear+1)%obj->size == obj->front )
    {
        return true;
    }
    return false;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }

    obj->rear = (obj->rear+1)%obj->size;
    obj->data[obj->rear] = value;

    if(obj->front == -1)
    {
        obj->front = 0;
    }
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }

    if(obj->front == obj->rear)
    {
        obj->data[obj->front] = -1;
        obj->front = -1;
        obj->rear = -1;      
    }
    else
    {
        obj->data[obj->front] = -1;
        obj->front = (obj->front+1)%obj->size;
    }
    return true;
}
//获取队首元素。如果队列为空,返回 -1 。
int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }  
    return obj->data[obj->front];
}
//获取队尾元素。如果队列为空,返回 -1 。
int myCircularQueueRear(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }  

    return obj->data[obj->rear];
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->data);
    obj->data = NULL;
    free(obj);
}

2、编程实践

参考题目连接
232-用栈实现队列
225-用队列实现栈
20-有效的括号
1047- 删除字符串中的所有相邻重复项

套用上面的常见操作接口,实现以下1047题

//把栈的一些通用接口作为模板记住, 以后做题的时候能够默写下来
typedef struct {
    char *data;		//栈中元素存放的地方
    int size;		//当前栈中有多少个元素
    int capacity;	//栈的最大深度
} MyStack;

MyStack *stackCreate(int capacity)
{
    MyStack *stack = (MyStack *)malloc(sizeof(MyStack));
    stack->data = (char *)malloc(sizeof(char)*capacity);
    stack->size = 0;
    stack->capacity = capacity;
    return stack;
}

void push(MyStack *obj, char value)
{
    obj->data[obj->size] = value;
    obj->size++;
}

void pop(MyStack *obj)
{
    obj->size--;
}

bool isEmpty(MyStack *obj)
{
    if(obj->size == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

char getTop(MyStack *obj)
{
    return obj->data[obj->size-1];
}

int getSize(MyStack *obj)
{
    return obj->size;
}

void stackfree(MyStack *obj)
{
    free(obj->data);
    obj->data = NULL;
    free(obj);
    obj = NULL;
}

//使用栈的思想
char * removeDuplicates(char * s)
{
    int i = 0;
    int len = strlen(s);
    MyStack *stk;

    //创建一个栈, 栈元素个数为len
    stk = stackCreate(len);

    for(i=0; i<len; i++)
    {
        //如果判断发现当前元素与栈顶元素相同时, 弹栈操作
        if( !isEmpty(stk) && getTop(stk) == s[i] )
        {
            pop(stk);
        }
        else
        {
            push(stk, s[i]);
        }
    }

    //遍历完成之后, 剩余的元素就是答案
    int size = getSize(stk);
    char *str = (char *)malloc(sizeof(char)*(size+1));
    for(i=0; i<size; i++)
    {
        str[size-1-i] = getTop(stk);
        pop(stk);
    }
    str[size] = '\0';

    //释放栈空间
    stackfree(stk);

    return str;
}
参考资料

数据结构C语言版

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值