数据结构整理——第三章 栈和队列

版权声明:个人整理,仅供参考,请勿转载,如有侵权,请联系[email protected] https://blog.csdn.net/mooe1011/article/details/88089325

考研时个人整理的,参考王道、严蔚敏等数据结构。

上一章——线性表:https://blog.csdn.net/mooe1011/article/details/88036093

下一章——树:https://blog.csdn.net/mooe1011/article/details/88089462

1. 栈

  1. 初始化S.top=-1,栈顶元素S.data[S.top]
  2. 如果栈顶指针为S.top=0,则进栈S.data[S.top++]=x,出栈x=S.data[–S.top],相应栈空栈满条件也会变化
  3. 共享栈 topl(左边)=-1,topr(右边)=MaxSize;当topr-topl=1
  4. 链式栈Lhead指向栈顶元素
  5. 链式入队,相当于头插法,p->next=Lhead->next;Lhead->next=p;
  6. n个不同元素进栈,出栈序列为(卡特兰数): ( 2 n ) ! ( n + 1 ) ! n ! \dfrac{(2n)!}{(n+1)!n!}
  7. 代码
    顺序栈
    #define MaxSize 50
    typedef struct {
        int data[MaxSize];
        int top;
    }SqStack;  //与顺序表差不多
    
    链式栈
    typedef struct LinkNode{
        int data;
        struct LinkNode *next;
    }*Listack;
  • 检查越界

    1. 栈满if(S.top==MaxSize-1)
    2. 栈空if(S.top==-1)
  • 进出栈

    1. 进栈 S.data[++S.top]=x; (先加)
    2. 出栈 x=S.data[S.top–]; (后减)
  • 判断栈序列是否合法

    int Judge (char A[]){
        int i=j=k=0;
        while(A[i]!='\0'){
            switch(A[i]){
                case 'I':j++;break;  //I代表入栈,O代表出栈,IOOO非法,IIOO合法
                case 'O':k++;
                if (k>j){
                    printf("非法\n");exit(0);
                }
            }
            i++;
        }
        if (j!=k){
            printf("非法\n");
            return false;
        } else {
            printf("合法\n");
            return true;
        }
    }

2. 队列

  1. 初始化:Q.front=Q.rear=0;
  2. 出队:Q.front=(Q.front+1)%MaxSize;
  3. 入队:Q.rear=(Q.rear+1)%MaxSize;
  4. 队满:(Q.rear+1)%MaxSize==Q.front
  5. 队空:Q.front=Q.rear(牺牲一个单元来区分队空) / 链表则是Q.front== NULL&&Q.rear== NULL;
  6. 队长:(Q.rear-Q.front+MaxSize)%MaxSize
  7. 链表删除元素时,只有一个结点时,删除后队列为空,要修改尾指针rear=front
  8. 代码
  • 顺序
    #define MaxSize 50
    typedef struct{
        int data[MaxSize];
        int front,rear;
    }SqQueue;
  • 入队
	if ((Q.rear+1)%MaxSize==Q.front)
        return false;
    Q.data[Q.rear]=x;
    Q.rear=(Q.rear+1)%MaxSize;
  • 出队
    if (Q.rear==Q.front)
        return false;
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;
  • 链表,Q.rear指向链尾
    typedef struct{     //结点
        int data;
        struct LinkNode *Next;
    }LinkNode;
    typedef struct{     //同时带头尾指针的单链表
        LinkNode *front,*rear;
    }LinkQueue;
  • 初始化

    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    Q.front->next=NULL;

  • 入队

    s=(LinkNode*)malloc(sizeof(LinkNode));
    s->data=x;
    s->next=NULL;
    Q.rear->next=s;
    Q.rear=s;
  • 出队
    if(Q.front==Q.rear) return false;
    p=Q.front->next;
    x=p->data;
    Q.front->next=p->next;
    if(Q.rear==p)       //只有一个结点
        Q.rear=Q.front;
    free(q);

3. 应用

  1. 栈的应用:括号匹配、迷宫求解、进制转换; 队的应用:缓冲区、广度优先搜索、树的层次遍历
  • 括号匹配

      bool BracketCheck(char *str){
          InitStack(s);  int i=0;
          while (str[i]!='\0'){
              switch(str[i]){
                  case '(':Push(S,'(');break;
                  case '[':Push(S,'[');break;
                  case '{':Push(S,'{');break;
                  case ')':Pop(S,e);
                      if(e!='(') return false;
                  break;
                  ....        //其他同理
                  default :break;
              }
              i++;
          }
          if (!IsEmpty(S)){
              printf("不匹配\n"); return false;
          } else {
              printf("匹配\n"); return true;
          }
      }
    
    
    
  • 后缀式求值

    int Op(int a,char op,int b){
        switch(Op){
            case '+':return a+b;break;
            case '-':return a-b;break;
            case '*':return a*b;break;
            case '/':
                if(b==0){
                    cout<<"ERROR"<<endl;
                    return false;
                } else return a/b;
        }
    }
    
    int com(char exp[]){
        int a,b,c,i=0;        //a、b为操作数;c为结果
        char Op;
        InitStack(s);
        while (exp[i]!='\0'){
            if(exp[i]>='0'&&exp[i]<='9'){       //注意只算一位就可以了
                Push(S,exp[i]-'0');     //字符型转换为整形
            } else {
                Op=exp[i];
                Pop(S,b);
                Pop(S,a);
                c=Op(a,Op,b);
                Push(S,c);
            }
        }
    }

4. 矩阵压缩存储

  1. 数组

    1. 一维:LOC(ai)=LOC(a0)+i*L
    2. 二维(以行优先,h为列下标):LOC(ai,j)=LOC(a0,0)+[i*(h+1)+j]*L
  2. 矩阵压缩

    1. 对称:n阶压缩后有(1+n)n/2个元素;
      ai,j与数组Bk的关系为(k从零开始)
      1. 当i>=j时,下三角及对角线元素, k = i ( i 1 ) 2 + j 1 k=\dfrac{i(i-1)}{2}+j-1
      2. 当i<j时,上三角元素, k = j ( j 1 ) 2 + i 1 k=\dfrac{j(j-1)}{2}+i-1
    2. 下三角(上三角类似,具体看书):压缩后有(1+n)n/2+1个元素;
      1. 当i>=j时,下三角及对角线元素, k = i ( i 1 ) 2 + j 1 k=\dfrac{i(i-1)}{2}+j-1
      2. 当i<j时,上三角元素,全为0; k = n ( n + 1 ) 2 k=\dfrac{n(n+1)}{2}
    3. 带状矩阵 下标k=行i×2+列j-3
    4. 稀疏矩阵 (行标、列标、值)

5. 广义表

  • 线性表的推广
  • 第一个元素a1称为表头,其余称为表尾
  • 列表的元素可以是子表,子表的元素还可以是子表
  • 广义表表尾总是广义表(真题)
  • A=(),B=(e),D=(A,B,C)
  • C=(a,(b,c,d))表示长度为2,两个元素,分别为a和子表(b,c,d)
  • Gethead(B)=e;GetTail(B)=(),空表,没有尾
  • Gethead(D)=A;GetTail(D)=(B,C),出第一个为表头,其余为表尾
  • GetHead((B,C))=B,GetTail((B,C))=©,注意括号

如果您看了这篇文章觉得有用的话,请随意打赏,您的支持将鼓励我继续创作,谢谢!

猜你喜欢

转载自blog.csdn.net/mooe1011/article/details/88089325
今日推荐