zoukankan      html  css  js  c++  java
  • 数据结构导论 五 栈、队列和数组

     栈

    栈的定义:只是在表的一端进行插入和删除的线性表

    其中:允许插入及删除一端(表尾)称为栈顶(top)

               另一端(表头)称为栈底(Bottom)

    当表中没有元素时称为空栈

    S={i1,i2,i3,i4,i5,i6} 此时 i1称为栈底 i6称为栈顶

                      图1

    进栈:在栈顶插入一个元素

    出栈:在栈顶删除一个元素

                           图2

    特点:

    通过图2 可以看出栈中的元素都是依次进入栈里面,第一个进入到栈里的称为栈底,越往上越是栈顶,而出栈的第一个元素则是栈顶。栈是先进后出的原则,栈称为“后进先出线性表LIFO”

    栈的基本运算有哪些???

    1)初始化栈:InitStack(S);

    2)判断栈:EmptyStack(s);

    3)进栈:push (S,x);

    4)出栈:pop(s);

    5)取栈:Gettop(s);

    顺序栈以及常用名词

    栈容量:栈中可以存放的最大元素个数

    栈顶指针top:指示在当前栈顶元素在栈中位置

    栈空:栈中无元素时,表示栈空

    栈满:数组空间已被站满,成栈满

    下溢:当栈空时,再要求出栈运算,称为“下溢”

    上溢:当栈满时,再要求进栈运算,称为“上溢”

    栈的运算:

    初始化:

    1 int Inistack(Seqstk *stk){
    2 
    3 stk->top=0;
    4 
    5 return 1;
    6 
    7 }

    判断栈:

    1 int EmptyStack(SeqStk *stk){
    2 
    3 if(stl->top==0)retrun 1;
    4 
    5 esle reutn 0;}

    进栈:

    int push(seqstk *stk ,DataType x)
    if(stk->top == masize-1)//判断是否上溢
    {error("栈满");return 0;//上溢
    
    }
    else{
    stk->top++;//修改栈顶指针,
    stk->data[sq->top]=x//元素x插入新栈顶中
    return 1;
    }

    出栈:

    int pop(seqstk *stk){
    if(stk->top==0)//判断是否需要下溢
    {error("栈空");return 0;}//下溢
    else{
    stk->toop;return 1;}//修改栈顶指针,指向新栈顶
    }

    取栈顶元素

    1 DataType GetTop(SeqStk *stk)
    2 {
    3 if(EmptyStack(stk))
    4 return NULLData;
    5 else
    6 return stk->data[stk->top];
    7 }

    链栈的定义

    栈的链式存储结构称为链栈,他是运算受限的的单链表,插入和删除操作今现制在表头位置上进行。栈顶指针就是链表的头指针。

     链栈的如何运算呢???

    初始化:

    1 void InitStack(Lkstk *Ls){
    2 Ls=(LKstk*)malloc(sizeof(Lkstk));
    3 Ls->next=null;
    4 }

    判断栈

    1 nt EmptyStack(LkStk *LS)
    2 {
    3 if(LS->next= =NULL) return 1;
    4 else return 0;
    5 }

    进栈

    void Push (LkStk *LS, DataType x)
    { LkStk *temp;
    temp= (LkStk *) malloc (sizeof (LkStk));
    temp->data=x;
    temp->next=LS->next;
    LS->next=temp;
    }

    出栈

     1 int Pop (LkStk *LS)
     2 { LkStk *temp;
     3 if (!EmptyStack (LS))
     4 { temp=LS->next;
     5 LS->next=temp->next;
     6 free(temp);
     7 return 1;
     8 }
     9 else return 0;
    10 }

    取栈顶元素

    DataType GetTop(LkStk *LS)
    {
    if (!EmptyStack(LS))
    return LS->next->data;
    else
    return NULLData;
    }

    队列

    队列也是一种运算受限的的线性表

    队列:是只允许在表的一端进行插入,而在另一端进行阐述的线性表

    如果将栈比作一个口开的公交车(先下后上),那么队列就可以比作两口开的公交(前门进后门出)

    对头:允许删除一端称为对头(front)

    队尾:允许插入的另一端称为队尾(rear)

    队列:Q={a1,a2,a3,a4,a5,a5。。。}

     队列:先进先出FIFO 

     队列的基本运算都有那些???

    • 队列初始化 InitQueue(Q):
      • 设置一个空队列Q
    • 判队列空 EmptyQueue(Q):
      • 若队列Q为空,则返回值为1,否则返回值为0
    • 入队列 EnQueue(Q,x):
    •     将数据元素x从队尾一端插入队列,使其成为队列的新尾元素;
    • 出队列 OutQueue(Q):
      • 删除队列首元素;
    • 取队列首元素GetHead(Q):
      • 返回队列首元素的值。

    初始化:front=rear=0

    进队:rear加1,元素插入尾指针位置

    出队:front加1,去头指针所值位置

    顺序队列:

    上溢条件:sq.rear==maxsize-1(队满)

    下溢条件:sq.rear==sq.front(队列空)

    循环队列

    定义:为队列分配一块存储空间,并将这块存储空间看成头尾相连接的。

    循环队列的实现

    对插入即入队列:队尾指针增1

    sq.rea(sq.rear+1)1%maxsize

    对删除即出队:对头指针增1

    sq.front=(sq.front+1)%maxsize

    循环队列规定:

    下溢条件即队列空:CQ.front==CQ.rear

    上溢条件即队列满:尾指针从后面追上头指针

    (CQ.rear+1)%maxsize==cq.front(尾赶头)

    循环队列的基本运算:

    队列初始化

    1 void InitQueue(CycQue CQ){
    2 CQ.front=0;CQ.rear=0;}

    判断队列

    1 int EmptyQueue(CycQue CQ)
    2 {if (CQ.rear==CQ.front) return 1;
    3 else return 0;}

    入队列

    int EnQueue(CycQue CQ,DataType x)
    {if ((CQ.rear+1)%maxsize==CQ.front)
    {error(“队列满” );return 0;}
    else {CQ.rear=(CQ.rear+1)%maxsize;
    CQ.data[CQ.rear]=x;
    return 1;}
    }

    出队列

    int OutQueue(CycQue CQ)
    {if (EmptyQueue(CQ))
    {error(“队列空” ); return 0; }
    else {CQ.front=(CQ.front+1)%maxsize;
    return 1; }
    }

    取队列首元素

    DataType GetHead(CycQue CQ)
    {
    if (EmptyQueue(CQ))
    return NULLData;
    else
    return CQ.data[(CQ.front+1)%maxsize];
    }

    链队列的基本运算

    队列的初始化

    1 void init Queue(LkQue *LQ){
    2 LkQueNode *temp;
    3 temp=(LkQuenode*)malloc(sizeof(LkQueNode));
    4 LQ->front=temp;
    5 LQ->rear=temp;
    6 (LQ->front)->next=NULL;
    7 }

    判队列空

    1 Int EmptyQueue(LKQue LQ){
    2 if(LQ.rear==LQ.front)return 1;
    3 else return 0;
    4 }

    入队列:

    1 Void EnQueue(LkQue *LQ;DataType x)
    2 {
    3 LkQueNode *temp;
    4 temp=(LkQueNode *)malloc(sizeof(LkQueNode));
    5 temp->data=x;
    6 temp->next=NULL;
    7 (LQ->rear)->next=temp;
    8 LQ->rear=temp;
    9 }

    出队列:

     1 OutQueue(LkQue *LQ)
     2 { LkQueNode *temp;
     3 if (EmptyQueue(LQ))
     4 {error(“队空” ); return 0; }
     5 else {
     6 temp=(LQ->front)->next;
     7 (LQ->front)->next=temp->next;
     8 if (temp->next==NULL) LQ->rear=LQ->front;
     9 free(temp);
    10 return 1;
    11 }
    12 }

    取队列首元素

     1 DataType GetHead (LkQue LQ)
     2 {
     3 LkQueNode *temp;
     4 if (EmptyQueue(LQ))
     5 return NULLData;
     6 else {
     7 temp=LQ.front->next;
     8 return temp->data;
     9 }
    10 }

     数组

    数组可以看成一种特殊的线性表,其特殊在于,表中的数组元素本身也是一种线性表。

    数据的逻辑结构与运算

    数组是线性表的推广,其每个元素由一个值和一组下标组成,其中下标数称为数组的维数。

     二维数组Amn可以看成是m个行向量组成的向量,也可以看成是n个列向量组成的向量

    数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组通常只有两种基本运算:

    读:给定一组下标,读取相应的数据元素;

    写:给定一组下标,修改相应的数据元素;

    寻址公式:

    例如, 二维数组Amn按“行优先顺序”存储在内存中,假设每个元素占用k个存储单元

    元素aij的存储地址应是数组的基地址加上排在aij前面的元素所占用的单元数。因为aij位于第i行、第j列,前面i行一共有i×n个元素,第i行上aij前面又有j个元素,故它前面一共有i×n+j个元素,

    因此, aij的地址计算函数为:LOC(aij)=LOC(a00)+(i*n+j)*k 

     矩阵的压缩存储

    为了节省存储空间,我们可以对这类矩阵进行压缩存储:即为多个相同的非零元素值分配一个存储空间;对零元素不分配空间。

    1.对称矩阵:

    定义:在一个n阶方阵A中,若元素满足下述性质:aij=aji , 0<=i,j<n-1

    则成A为对称矩阵。

     

     物理存储:

    对称矩阵中元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间。

    它的公式:i=n(n+1)/2

    下标变换公式

    1)若i>=j,则下三角形中,a[ij]之前的i行(从第0行道第i-1行)一共由1+2+。。。=i(i+1)/2个元素,在第i行上,a[ij]之前由j个元素,

    因此有:k=i*(i+1)/2+j  0<=k<n(n+1)/2-1

    2)若i<j,则a[ij]是在上三角矩阵中,因为aij=aji,所以只要交换上述对应关系中的i和j即可得到

    k=j*(j+1)/2+i    0<=k<n(n+1)/2-1

     I=max(i,j)J=min(i,j),则ki, j的对应关系
    可统一为: k=I*(I-1)/2+J 0≤kn(n+1)/2 -1

     三角矩阵:

    三角矩阵中的重复元素C可共享一个存储空间,其余的元素正好有n(n+1)/2个,因此,三角矩阵可以压缩存储道向量s[0...n(n+1)/2]中,其中c存放在向量的最后一个分量中

    上三角:

     当i<=j时     k=i( 2n-1+1)/2+j-i

    当i>j时        k=n(n+1)/2

    下三角:

    当i>=j时: k=i(i+1)/2+j

    当i<j时:    k=j(j+1)/2+i

  • 相关阅读:
    c#常用的技巧
    在Web应用程序中使用Castle ActiveRecord
    Castle Query返回System.String程序报错的解决方法
    C++标准转换运算符const_cast
    Linux目录解释
    [转载]存储过程与函数的区别
    详解GCC的下载和安装
    Linux控制台的快捷键
    Linux下软件的安装和卸载
    电路交换,报文交换和分组交换
  • 原文地址:https://www.cnblogs.com/X404/p/12091207.html
Copyright © 2011-2022 走看看