数据结构学习笔记之栈和队列

1栈基本操作

//结构体定义
typedef struct {
    int top;
    char data[MaxSize]
} Stack;

//初始化
void InitStack(Stack *s) {
    memset(s->data, '.', sizeof(char) * MaxSize);
    s->top = -1;
}

//判空
_Bool isEmpty(Stack *s) {
    return s->top == MaxSize;
}

//判满
_Bool isFull(Stack *s){
    return s->top == MaxSize - 1;
}

//入栈
void Push(Stack *s, char element) {
    if (s->top != (MaxSize - 1))
        s->data[++s->top] = element;
}

//出栈
void Pop(Stack *s) {
    if (s->top != -1)
        s->top--;
}

//读取栈顶元素
char getTop(Stack *s) {
    char topElement = s->data[s->top];
    return topElement;
}

2 利用栈判断回文

//有一段字符串使用字符数组存储,使用栈判断该字符串是否是回文
_Bool IsPalindrome(char *str, int len) {
    Stack *s = (Stack *) malloc(sizeof(Stack));
    InitStack(s);
    int IsOdd = len % 2 ? 1 : 0;

    int index = 0;
    while (index < len)
        if (index < len / 2) {
            Push(s, str[index]);
            index++;
        } else if (index == len / 2 && IsOdd)   //字符串长度为奇数,从中间位置的后一位开始比较
            index++;
        else {   //回文比较
            if (str[index] == getTop(s)) {   //当前字符与栈顶元素相匹配
                Pop(s);
                index++;
            } else return 0;
        }
    return 1;
}

3 括号匹配

//判断一个算数表达式的括号(包含 "()、[]、{}")是否匹配正确
_Bool IsCorrectMatch(const char *str) {
    Stack *s = (Stack *) malloc(sizeof(Stack));
    InitStack(s);
    while (*str != '\0') {
        if (*str == '(' || *str == '[' || *str == '{')
            Push(s, *str);
        if (*str == ')' || *str == ']' || *str == '}') {
            if ((*str == ')' && getTop(s) == '('))
                Pop(s);
            else if ((*str == ']' && getTop(s) == '['))
                Pop(s);
            else if ((*str == '}' && getTop(s) == '{'))
                Pop(s);
            else
                return 0;
        }
        str++;
    }
    return 1;
}

4 设计共享栈

//使用一个顺序表来设计两个栈 s1 和 s2 的相关操作,type 为 'l' 表示左栈 s1,为 'r' 表示右栈 s2
typedef struct {
    int data[MaxSize];
    int topL;
    int topR;
} ToStack;

//初始化
void ToInitStack(ToStack *s) {
    memset(s->data, 0, sizeof(int) * MaxSize);
    s->topL = -1;
    s->topR = MaxSize;
}

//判空
_Bool ToIsEmpty(ToStack *s, char type) {
    if ((type == 'l' && s->topL == -1) || (type == 'r' && s->topR == MaxSize))
        return 1;
    else
        return 0;
}

//判满
_Bool ToIsFull(ToStack *s) {
    if (s->topR - s->topL > 1)
        return 0;
    else
        return 1;
}

//入栈
void ToPush(ToStack *s, char type, int val) {
    if (!ToIsFull(s)) { //栈不满则入栈
        if (type == 'l')
            s->data[++s->topL] = val;
        else
            s->data[--s->topR] = val;
    } else
        printf("STACK OVERFLOW !");
}

//出栈
void ToPop(ToStack *s, char type) {
    if (type == 'l') {
        if (!ToIsEmpty(s, type)) {
            s->data[s->topL] = 0;
            s->topL--;
        } else
            printf("STACK IS EMPTY !");
    } else {
        if (!ToIsEmpty(s, type)) {
            s->data[s->topR] = 0;
            s->topR++;
        } else
            printf("STACK IS EMPTY !");
    }
}

//读取栈顶元素
int ToGetTop(ToStack *s, char type) {
    if (type == 'l')
        return s->data[s->topL];
    else
        return s->data[s->topR];
}

5 栈模拟队列

//使用两个栈来模拟一个队列,实现队列的入列、出列、判空操作
typedef struct {
    struct Stack *s1;
    struct Stack *s2;
} Queue;

void InitQueue(Queue *q) {
    memset(q->s1.data, 0, sizeof(int) * MaxSize);
    q->s1.top = -1;
    memset(q->s2.data, 0, sizeof(int) * MaxSize);
    q->s2.top = -1;
}

_Bool QueueEmpty(Queue *q) {
    if (q->s1->top == -1 && q->s2->top == -1)
        return 1;
    else
        return 0;
}

void JoinQueue(Queue *q, char val) {
    if (!isEmpty(q->s1))
        Push(q->s1, val);
}

void LeaveQueue(Queue *q) {
    while (q->s1.top != -1) {    //s1 中元素转移到 s2,然后出栈来模拟出队列
        Push(q->s2, q->s1->data[cur]);
        q->s1.top--;
    }
    Pop(q->s2);
}

6 操作序列是否合法

//假设入栈和出栈分别用 I 和 O 表示,判断操作序列是否合法
_Bool IsItLegal(char *str) {
    int count = -1;
    while (*str != '\0'){
        if (*str == 'I'){
            if (count < MaxSize - 1)
                count++;
            else return 0;
        } else if (*str == 'O'){
            if (count > -1)
                count--;
            else return 0;
        }
        str++;
    }
    return 1;
}

7 进制转换

//利用栈的思想,将一个非负十进制正整数转化为二进制
void DecimalToBinary(int val) {
    Stack *s = (Stack*)malloc(sizeof(Stack));
    InitStack(s);
    do {
        Push(s, val%2);
        val /= 2;
    }while (val);
    while (s->top != -1){
        printf("%d", getTop(s));
        Pop(s);
    }
}

8 栈存储数据

//设读入一整数的序列:a1, a2, a3,…,an,试编写算法实现:用栈结构存储输入的整数,当 ai != -1 时
//将 ai 进栈;当 ai == -1 时,输出栈顶整数并出栈。算法应对异常情况(入栈满等)给出相应的信息
void SaveData(Stack *s, int *val, int len) {
    for (int i = 0; i < len; ++i) {
        if (val[i] != -1){
            if (!isFull(s)){
                Push(s, val[i]);
                printf("Not meet -1, Push %d\n", val[i]);
            } else{
                printf("STACK OVERFLOW !");
                return;
            }
        } else{
            if (!isEmpty(s)){
                printf("Meet -1, Pop %d\n", getTop(s));
                Pop(s);
            } else{
                printf("STACK EMPTY !");
                return;
            }
        }
    }
}

9 中缀转逆波兰

//将所给的中缀算术表达式转换成对应的后缀表达式(逆波兰表达式)
void SuffixExpression(Stack *s, char *str) {
    while (*str != '\0'){
        switch (*str) {
            // + 和 - 的优先级低于 * 和 /,依次从栈顶弹出比 + 和 - 优先级高的和相等的运算符
            //直至遇到一个优先级比他低的或者左括号为止
            case '+':
                while (s->top != -1){
                    if (getTop(s) == '*' || getTop(s) == '/' || getTop(s) == '-') {
                        printf("%c", getTop(s));
                        Pop(s);
                    }
                    if (getTop(s) == '(')   //遇到左括号,终止出栈
                        break;
                }
                //比他优先级高或相等的出栈结束,它入栈
                Push(s, *str);
                break;
            case '-':
                while (s->top != -1){
                    if (getTop(s) == '*' || getTop(s) == '/' || getTop(s) == '+') {
                        printf("%c", getTop(s));
                        Pop(s);
                    }
                    if (getTop(s) == '(')   //遇到左括号,终止出栈
                        break;
                }
                //比他优先级高或相等的出栈结束,它入栈
                Push(s, *str);
                break;
            case '*':   //当前元素为 * 或 /,有优先级最高,直接入栈
                Push(s, *str);
                break;
            case '/':
                Push(s, *str);
                break;
            case '(':   //当前为左括号,入栈
                Push(s, *str);
                break;
            case ')':   //当前为右括号
                while (s->data[s->top] != '('){ //依次将栈中元素输出,直至出现 '('
                    printf("%c", getTop(s));
                    Pop(s);
                }
                //删除 '('
                Pop(s);
                break;
            default:    //其余情况下,为表达式中的常量,直接输出
                printf("%c", *str);
        }
        str++;
    }
    //将栈中的剩余元素依次出栈
    while (s->top != -1){
        printf("%c", getTop(s));
        Pop(s);
    }
}

队列

1 队列基本操作

//循环队列结构体
typedef struct {
    int data[MaxSize];
    int front;
    int rear;
}Queue;

//初始化
void Init(Queue *q){
    memset(q->data, 0, sizeof(int) * MaxSize);
    q->front = q->rear = 0;
}

判空
_Bool IsEmpty(Queue *q){
    return q->rear == q->front;
}

//判满
_Bool IsFull(Queue *q){
    return (q->rear + 1) % MaxSize == q->front;
}

//入队(队头入队)
void JoinQueue(Queue *q, int val){
    if (!IsFull(q)){
        q->data[q->rear] = val;
        q->rear = (q->rear + 1) % MaxSize;
    } else{
        printf("QUEUE OVERFLOW !");
        return;
    }
}

//出队(队尾离队)
void LeaveQueue(Queue *q){
    if (!IsEmpty(q)){
        q->data[q->front] = 0;
        q->front = (q->front + 1) % MaxSize;
    } else{
        printf("QUEUE EMPTY !");
        return;
    }
}

//获取队尾元素
int GetRear(Queue *q){
    if (!IsEmpty(q))
        return q->data[q->rear-1];
    else return -1;
}

//循环队列的其他操作与顺序表类似,链队的操作与单链表类似,这里省略
posted @ 2021-11-01 16:27  悟道九霄  阅读(78)  评论(0编辑  收藏  举报