资讯详情

数据结构-栈和队列>

在这里插入图片描述

文章目录

    • 定义引入
    • 栈的定义
    • 关于栈的细节
  • 栈操作
    • 栈的初始化
    • 初始化空栈
    • 删除栈
    • 入栈
    • 出栈
  • 链栈
    • 创建链栈`
    • 链式入栈
    • 链式出栈
    • 思想应用-括号匹配问题
  • 循环队列
    • 定义
    • 循环队列的思考
    • 解决
    • 队列操作
  • 队列思想的应用-旋转数组
    • 思路
    • 代码

定义引入

  .当我们把子弹放在玩具枪上时,我们的操作是取出弹匣,从底部依次将子弹送入弹匣。如果我们想让弹匣变空,我们会一个接一个地取出子弹。细心的人可能知道先把它放进去,然后再把它拿出来。这种先进的后出是栈的体现 

栈的定义

 1.栈(stack)限制只允许在表尾插入和删除的线性表。  2.我们称允许插入和删除的一面为栈顶(top),另一端称为栈底。 没有任何元素的栈叫空栈。 

关于栈的细节

1.首先是线性表,即栈元素有线性关系,即前驱后继关系。 2.只是它是一种特殊的线性表。定义上说,插入和删除在线表的表尾, 它的,它总是只进栈顶 这使得栈底固定,最先进的栈底只能在栈底。 3. 4

栈操作

栈的初始化

typedef struct { 
             int stacksize;///栈最大容量     int *top;//栈顶指针,注意=栈顶指针总是在栈顶元素的下一个,便于计算     int *base;//栈底指针 } sqstack;//顺序栈 sqstack *S 

#####关于初始化

初始化空栈

首先要知道需要知道,当栈为空时,栈顶指针等于栈底指针S->top == S->base; 
///初始化空栈 void initstack(sqstack *S, int n) { 
             S->base = (int*)malloc(sizeof(n));     if(!S->base) { 
                 exit(0);     }     S->stacksize = n;     S->top = S->base; }
```c
//当top=base的时候,此时的栈顶等于栈底,栈自然就和清空了
//清空栈
void clearstack(sqstack *S) { 
        
    S->top = S->base;//线性表不是链表我们直接让top=base;中间的元素就消除了
}

删除栈

//销毁栈
void deletestack(sqstack *S) { 
        
    if(S->base) { 
         //栈存在
        S->stacksize = 0;
        S->top = S->base = NULL;
    }
}			

入栈

正常情况下入栈前进行栈是否已经满进行判断(s->top == s-> base)
void pushstack(sqstack *S, int e) { 
        
    //判断栈满
    if(S->top - S->base == S->stacksize) { 
        
        printf("栈满");
    } else { 
        
        *S->top = e;//先赋值,top向上走1个位置
             S->top++;//*S->top++=e;
    }
}

出栈

//顺序出栈
void stackpop(sqstack*S, int e) { 
        
    if(S->top == S->base) { 
        
        printf("栈空"); //栈空,无法返回元素
    } else { 
        
        e = *--S->top; //因为top是栈顶元素的下一个位置,所以该语句=*S->top--;e=S->top;
    }
}

链栈

定义:栈的链式存储结构,我们知道栈是对top指针进行操作的,那么链栈就是将栈的
top指针变成了head头指针,合二为一,也就是对于链栈来说是不需要头节点的;

创建一个链栈`

typedef struct StackNode { 
        
   int data;               //存放栈的数据
   struct StackNode *next;
} StackNode, *LinkStackPtr;


typedef struct LinkStack1 { 
        
    LinkStackPtr top;         //top指针
    int count;                 // 栈元素计数器
} LinkStack;

`

链式入栈

int StatusPush(LinkStack *s, int e) { 
        
     LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
     p->data = e;
     p->next = s->top;//前栈顶元素直接复赋值给新节点的直接后继//
     s->top = p;
     s->count++;
     return 1;
}

链式出栈

int StatusPop(LinkStack *s, int *e) { 
        
    LinkStackPtr p;
    *e = s->top->data;
    p = s->top;
    s->top = s->top->next;
    free(p);
    s->count--;
    return 1;
}

栈的思想应用-括号匹配问题

//#include<stdio.h>
//#include<string.h>
//int isValid(char * s) { 
        
// int len = strlen(s);
// if (len % 2 != 0) { 
        
// return 0;
// } //直接进行判断,如果字符串的长度是技术我们就直接返回0
// char stack[len]; //定义一个栈 模拟
// int i, top = -1;//栈顶指针 top = -1 当top = -1 的时候 栈内没有元素,top = 0的时候栈的元素是一个
// for( i = 0; i < len; i++) { 
        
// if(s[i] == '(' || s[i] == '{' || s[i] == '[') { 
        
// stack[++top] = s[i]; //左括号入栈
// } else { 
        
// if (top == -1){ 
        
// return 0; //当不是左括号的时候进行判断,栈为空,不匹配
// }
// char cur = stack[top--]; //左括号和当前字符匹配,左右不匹配return 0
// if (s[i] == ')' && cur != '(') { 
        
// return 0;
// } else if (s[i] == '}' && cur != '{') { 
        
// return 0;
// } else if (s[i] == ']' && cur != '[') { 
        
// return 0;
// }
// }
// }
// if(top != -1) { 
        
// return 0; //栈不为空说明栈内还有元素,不匹配
// } else { 
        
// return 1; //栈空无元素 = 匹配
// }
//}

循环队列

定义

队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
我们把允许插入的一端称队伍尾巴,进行删除操作的一端称为队头
为了防止队列的溢出我们一般创建的是循环队列;

循环队列的思考

此时问题叉出来了,我们刚才说,空队列时,front 等于rear,现在当队列满 时,也是front 等于reat,那么如何判断此时的队列究竟是空还是满呢? 办法一是设置一个标志变量 Aag, 当front == teat, 且flag= 0时为队列空, 当front == reat,且 fag=1时为队列满。 •办法二是当队列空时,条件就是 front =teat,当队列满时,我们修改其条 件,保留一个元素空间。也就是说,队列满时,数组中还有一个室闲单元。 我们就认为此队列已经满了,也就是说,我们队列中没有空的格子出现

解决

因此我们判断队列是否已经全部填满的条件就是 (rear+1)%QSIZE == front;
通用的计算队列的长度公式 (rear-fonrt+qsiez)%qsize;

队列操作

#include<stdio.h>
#include<stdlib.h>
# define MAXSIZE 1000
typedef struct ndoe { 
        
    int data[MAXSIZE];
    int front;
    int rear;
} Sq;
//初始化一个空队列
void initsq(Sq *Q) { 
        
    Q->front = Q->rear = 0;
}
//求队列的长度,返回长度
int  lensq(Sq *Q) { 
        
    return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}
//循环入队
void insertsq(Sq *Q, int e) { 
        
    //判断队满
    if ((Q->rear + 1) % MAXSIZE == Q->front){ 
        
        printf("队满");
    } else { 
        
        Q->data[Q->rear] = e;
        Q->rear = (Q->rear + 1) % MAXSIZE;
    }
}

//循环出队列
void  gosq(Sq *Q, int  *e) { 
        

    if (Q->front == Q->rear) { 
        
        printf("队空");
    } else { 
        
        *e = (Q->data[Q->front]);
        Q->front = (Q->front+1) % MAXSIZE;//front 没有到最后的位置的时候front后一个位置,若在最后采用模方法把它放到第一个
    }
}

队列思想的应用——旋转数组

思路

思考:我们已经知道了要旋转k次,现在开辟一个数组把我们把我们这个数组的元素一次放进去,之后我们光给下标加k是不行的,这存在很明显的越界问题,这个时候就想到了刚才循环队列的思想,我们知道了数组的长度SIZE我们的元素存放的位置就是(i(当前下标)+k )%SIZE;

代码

void rotate(int* nums, int numsSize, int k) { 
        
    int nums1[numsSize], i;
    for(i = 0; i < numsSize; i++) { 
        
        nums1[i] = nums[i];
    }  
    for(i=0; i < numsSize; i++) { 
        
        nums[(i+k) % numsSize] = nums1[i];
    }
    return nums;
}

标签: fag中轴力矩传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台