第2章:线性数据结构

第2章:线性数据结构

1、实现顺序栈的判空操作

/**********
【题目】试写一算法,实现顺序栈的判空操作
StackEmpty_Sq(SqStack S)。
顺序栈的类型定义为:
typedef struct {
  ElemType *elem; // 存储空间的基址
  int top;        // 栈顶元素的下一个位置,简称栈顶位标
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack;        // 顺序栈
***********/
Status StackEmpty_Sq(SqStack S)
/* 对顺序栈S判空。                      */ 
/* 若S是空栈,则返回TRUE;否则返回FALSE */
{
    if(S.top != 0) return FALSE;
    else return TRUE;
}

2、实现顺序栈的取栈顶元素操作

/**********
【题目】试写一算法,实现顺序栈的取栈顶元素操作
GetTop_Sq(SqStack S, ElemType &e)。
顺序栈的类型定义为:
typedef struct {
  ElemType *elem;  // 存储空间的基址
  int top;         // 栈顶元素的下一个位置,简称栈顶位标
  int size;        // 当前分配的存储容量
  int increment;   // 扩容时,增加的存储容量
} SqStack;         // 顺序栈
***********/
Status GetTop_Sq(SqStack S, ElemType &e) 
/* 取顺序栈S的栈顶元素到e,并返回OK; */ 
/* 若失败,则返回ERROR。              */
{
   if(S.top == 0) return ERROR;
   e = S.elem[S.top - 1];
   return OK;
}

3、实现顺序栈的出栈操作

/**********
【题目】试写一算法,实现顺序栈的出栈操作
Pop_Sq(SqStack &S, ElemType &e)。
顺序栈的类型定义为:
typedef struct {
  ElemType *elem;  // 存储空间的基址
  int top;         // 栈顶元素的下一个位置,简称栈顶位标
  int size;        // 当前分配的存储容量
  int increment;   // 扩容时,增加的存储容量
} SqStack;         // 顺序栈
***********/
Status Pop_Sq(SqStack &S, ElemType &e) 
/* 顺序栈S的栈顶元素出栈到e,并返回OK;*/ 
/* 若失败,则返回ERROR。               */
{
    if(S.top == 0) return ERROR;
    //这里--S.top既可以找到栈顶元素
    //也可以实现栈顶位标减1
    e = S.elem[--S.top];
    return OK;
}

4、重新定义顺序栈,构建初始容量和扩容增量分别为size和inc的空顺序栈S

/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
构建初始容量和扩容增量分别为size和inc的空顺序栈S。
typedef struct {
  ElemType *elem; // 存储空间的基址
  ElemType *top;  // 栈顶元素的下一个位置
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack2;
***********/
Status InitStack_Sq2(SqStack2 &S, int size, int inc)
/* 构建初始容量和扩容增量分别为size和inc的空顺序栈S。*/ 
/* 若成功,则返回OK;否则返回ERROR。                 */
{
    //考虑size、inc值不合理的情况
    if(size <= 0 || inc <= 0) return ERROR;
    //这里开辟的空间是ElemType而不是SqStack2
    S.elem = S.top = (ElemType *)malloc(sizeof(ElemType)*size);
    if(S.elem == NULL) return ERROR;
    S.size = size;
    S.increment = inc;
    return OK;
}

5、重新定义顺序栈,实现顺序栈的判空操作

/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的判空操作。
typedef struct {
  ElemType *elem; // 存储空间的基址
  ElemType *top;  // 栈顶元素的下一个位置
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack2;
***********/
Status StackEmpty_Sq2(SqStack2 S)
/* 对顺序栈S判空。                      */ 
/* 若S是空栈,则返回TRUE;否则返回FALSE */
{
     //同地址为空栈
     if(S.elem != S.top)return FALSE;
     else return TRUE;
}

6、重新定义顺序栈,实现顺序栈的入栈操作

/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的入栈操作。
typedef struct {
  ElemType *elem; // 存储空间的基址
  ElemType *top;  // 栈顶元素的下一个位置
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack2;
***********/
Status Push_Sq2(SqStack2 &S, ElemType e)
/* 若顺序栈S是满的,则扩容,若失败则返回ERROR。*/
/* 将e压入S,返回OK。                          */
{
    int i = 0;
    ElemType *temp = S.elem;
    while(temp != S.top)/*找到两者地址相等,此时i表示有多少个元素,类似顺序栈1中top的作用*/ 
    {
        i++;
        temp ++;
    }
    temp = S.elem;
    if(i == S.size){
        /*内存重新分配,之所以用另一个变量来存储有以下原因:内存分配有几种情况(这个函数不太安全)*/
        /*
            1、若已有内存后面还存在increment个连续地址,则把后面的increment内存纳入数组中,此时temp的地址跟S.elem一致;
            2、如果原来的内存后面没有足够的空闲空间用来分配,那么会在栈中重新找一块newSize大小的内存,然后把已有内存的数据复制到新内存中(数据已移动),把新内存的地址返回给temp,而老块内存重新放回栈中
            3、如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回null而原来的内存块保持不变。
            4、如果S.elem为null,则realloc()和malloc()类似。分配一个newsize的内存块,返回一个指向该内存块的指针。
            5、如果newsize大小为0,那么释放S.elem指向的内存,并返回null。 

            综上,这就是为什么重新分配内存时要定义一个临时指针,并最后把该指针指向NULL
        */
       temp = (ElemType *)realloc(S.elem,sizeof(ElemType)*(S.size
       +S.increment));
       if(temp == NULL)return ERROR;
       S.elem = temp;
       /*注意,之前这里如果没有下面这行代码,
        若如果原本已有六个元素(size),
        则测试不通过,经调试发现:
        那个temp在内存重新分配后不一定是指向S.elem的值
        所以这时候S.top跟S.elem的地址差距甚大
        */
       S.top = S.elem + i;
       S.size += S.increment; 
       temp = NULL;  
    }
    *(S.top ++) = e;    
    return OK;
}

7、重新定义顺序栈,实现顺序栈的出栈操作

/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的出栈操作。
typedef struct {
  ElemType *elem; // 存储空间的基址
  ElemType *top;  // 栈顶元素的下一个位置
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack2;
***********/
Status Pop_Sq2(SqStack2 &S, ElemType &e) 
/* 若顺序栈S是空的,则返回ERROR;    */ 
/* 否则将S的栈顶元素出栈到e,返回OK。*/
{
    if(S.elem == S.top) return ERROR;
    e = *(--S.top);
    return OK;
}

8、借助辅助栈,复制顺序栈S1得到S2

/**********
【题目】试写一算法,借助辅助栈,复制顺序栈S1得到S2。
顺序栈的类型定义为:
typedef struct {
  ElemType *elem; // 存储空间的基址
  int top;        // 栈顶元素的下一个位置,简称栈顶位标
  int size;       // 当前分配的存储容量
  int increment;  // 扩容时,增加的存储容量
} SqStack;        // 顺序栈
可调用顺序栈接口中下列函数:
Status InitStack_Sq(SqStack &S, int size, int inc); // 初始化顺序栈S
Status DestroyStack_Sq(SqStack &S); // 销毁顺序栈S
Status StackEmpty_Sq(SqStack S);    // 栈S判空,若空则返回TRUE,否则FALSE
Status Push_Sq(SqStack &S, ElemType e); // 将元素e压入栈S
Status Pop_Sq(SqStack &S, ElemType &e); // 栈S的栈顶元素出栈到e
***********/
Status CopyStack_Sq(SqStack S1, SqStack &S2) 
/* 借助辅助栈,复制顺序栈S1得到S2。    */ 
/* 若复制成功,则返回TRUE;否则FALSE。 */
{
     //先初始化
     Status status = InitStack_Sq(S2,S1.size,S1.increment);
     if(status == OVERFLOW)return FALSE; 
     if(S1.top == 0) return TRUE;
     for(int i = 0;i < S1.top;i ++){
        Push_Sq(S2,S1.elem[i]);
     }
     DestroyStack_Sq(S1);
     return OK;
}

9、求循环队列的长度

/**********
【题目】试写一算法,求循环队列的长度。
循环队列的类型定义为:
typedef struct {
  ElemType *base;  // 存储空间的基址
  int front;       // 队头位标
  int rear;        // 队尾位标,指示队尾元素的下一位置
  int maxSize;     // 最大长度
} SqQueue;
***********/
int QueueLength_Sq(SqQueue Q)
/* 返回队列Q中元素个数,即队列的长度。 */ 
{
    //保留一个内存空间不用的方案
    //有两种情况:rear在front后;rear在front前
    return (Q.rear-Q.front+Q.maxSize)%Q.maxSize;
}

10、设置一个标志域tag标记队列的空或满,编写与此结构相应的入队列和出队列的算法

/**********
【题目】如果希望循环队列中的元素都能得到利用,
则可设置一个标志域tag,并以tag值为0或1来区分尾
指针和头指针值相同时的队列状态是"空"还是"满"。
试
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值