数据结构之线性关系的C语言实现过程

线性表

顺序表、链表

顺序栈

声明过程

#include "constants.h"

#define STACK_INIT_SIZE 20 //顺序栈存储空间的初始分配量
#define STACKINCREMENT 5   //顺序栈存储空间的分配增量

typedef int SElemType;

typedef struct
{
    SElemType *base; //栈底指针,始终指向存储空间的基地址
    SElemType *top;  //栈顶指针,指向栈顶元素的下一个位置
    int stacksize;   //数组存储空间的长度
} SqStack;

Status InitStack(SqStack &S); //构造一个空的栈S

Status StackEmpty(SqStack S); //判断栈S是否是空表,若是,则返回TURE,不是,则返回FALSE

Status StackFull(SqStack S); //判断栈S是否是已满,若是则返回TRUE,否则返回FALSE

int StackLength(SqStack &S); //返回栈S的长度

Status GetTop(SqStack S, SElemType &e); //得到栈S的栈顶元素,并且用变量e带回

Status Push(SqStack &S, SElemType e); //把元素e的值进行入栈操作

Status Pop(SqStack &S, SElemType &e); //出栈操作,出栈的元素用变量e来带回

Status ClearStack(SqStack &S); //重置栈S为空栈

Status StackTraverse(SqStack S, Status (*visit)(SElemType)); //依次对栈S中的每个元素调用visit进行访问

Status DestroyStack(SqStack &S); //销毁栈S,可能的话释放其空间

Status visit_read(SElemType e); //访问函数

Status Adjust(SqStack &S); //扩大栈S的最大存储空间

实现过程

#include "sqstack.h"
#include <stdio.h>
#include <stdlib.h>

Status InitStack(SqStack &S)
{
    S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    //栈的连续空间分配
    if (!S.base)
        exit(OVERFLOW);
    S.top = S.base; //空栈,初始化栈顶指针
    S.stacksize = STACK_INIT_SIZE;
    return OK;
}

Status StackEmpty(SqStack S)
{
    /* return S.top == S.base ? TRUE : FALSE; */
    return S.top == S.base;
}

Status StackFull(SqStack S)
{
    return S.top - S.base == S.stacksize;
}

int StackLength(SqStack &S)
{
    return S.top - S.base;
}

//Attention!!   top指针指向的是栈顶元素的下一个位置
Status GetTop(SqStack S, SElemType &e)
{
    /* if (!StackEmpty(S))
    {
        e = *(S.top - 1);
        return OK;
    }
    else
        return ERROR; */
    if (S.top == S.base)
        return ERROR;
    else
    {
        e = *(S.top - 1);
        return OK;
    }
}

//*和++运算符都是同级的,自右向左。
Status Push(SqStack &S, SElemType e)
{
    if (StackFull(S))
        Adjust(S);
    *S.top++ = e;
    return OK;
}

//不能用*S.top--,而应该用*--S.top。因为top指向栈顶元素的下一个元素
Status Pop(SqStack &S, SElemType &e)
{
    if (StackEmpty(S))
        return ERROR;
    else
    {
        e = *--S.top;
        return OK;
    }
}

Status ClearStack(SqStack &S)
{
    S.top = S.base;
    return OK;
}

Status StackTraverse(SqStack S, Status (*visit)(SElemType))
{
    /* if (StackEmpty(S))
        return ERROR;
    else
    {
        SElemType *p = S.base;
        while (p != S.top)
        {
            if (!visit(*p))
                return ERROR;
            p++;
        }
        return OK;
    } */
    SElemType *p;
    for (p = S.base; p < S.top; p++)
        if (!visit(*p))
            return ERROR;
    return OK;
}

Status DestroyStack(SqStack &S)
{
    if (S.base)
        free(S.base);
    S.base = NULL;
    return OK;
}

Status visit_read(SElemType e)
{
    printf("%d ", e);
    return OK;
}

Status Adjust(SqStack &S)
{
    S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
    if (!S.base)
        exit(OVERFLOW);
    S.top = S.base + S.stacksize;
    S.stacksize += STACKINCREMENT;
    return OK;
}

链栈

声明过程

#include "constants.h"

typedef int SElemType;

typedef struct Snode
{
    SElemType data;
    struct Snode *next;
} SNode, *LinkStack;

Status InitStack(LinkStack &S); //构造一个空的栈S

Status StackEmpty(LinkStack S); //判断栈S是否是空表,若是,则返回TURE,不是,则返回FALSE

int StackLength(LinkStack &S); //返回栈S的长度

Status GetTop(LinkStack S, SElemType &e); //得到栈S的栈顶元素,并且用变量e带回

Status Push(LinkStack &S, SElemType e); //把元素e的值进行入栈操作

Status Pop(LinkStack &S, SElemType &e); //出栈操作,出栈的元素用变量e来带回

Status ClearStack(LinkStack &S); //重置栈S为空栈

Status StackTraverse(LinkStack S, Status (*visit)(SElemType)); //依次对栈S中的每个元素调用visit进行访问

Status DestroyStack(LinkStack &S); //销毁栈S,可能的话释放其空间

Status visit_read(SElemType e); //访问函数

实现过程 

#include "linkstack.h"
#include <stdlib.h>
#include <stdio.h>

//S(linkstack)是头指针(一个S代表一个链栈),它指向栈顶元素所在节点
Status InitStack(LinkStack &S)
{
    S = (LinkStack)malloc(sizeof(SNode *));
    if (!S)
        exit(OVERFLOW);
    S = NULL;
    return OK;
}

Status StackEmpty(LinkStack S)
{
    return S == NULL ? TRUE : FALSE;
}

int StackLength(LinkStack &S)
{
    int len = 0;
    SNode *p = S;
    while (p)
    {
        p = p->next;
        len++;
    }
    return len;
}

Status GetTop(LinkStack S, SElemType &e)
{
    if (!S)
        return ERROR;
    else
    {
        e = S->data;
        return OK;
    }
}

Status Push(LinkStack &S, SElemType e)
{
    SNode *p = (SNode *)malloc(sizeof(SNode));
    if (!p)
        exit(OVERFLOW);
    p->data = e;
    p->next = S;
    S = p;
    return OK;
}

Status Pop(LinkStack &S, SElemType &e)
{
    if (!S)
        return ERROR;
    else
    {
        SNode *p = S;
        e = p->data;
        S = p->next;
        free(p);
        return OK;
    }
}

Status ClearStack(LinkStack &S)
{
    while (S)
    {
        SNode *p = S;
        S = p->next;
        free(p);
    }
    return OK;
}

Status StackTraverse(LinkStack S, Status (*visit)(SElemType))
{
    SNode *p = S;
    while (p)
    {
        if (!visit(p->data))
            return ERROR;
        p = p->next;
    }
    return OK;
}

Status DestroyStack(LinkStack &S)
{
    ClearStack(S);
    free(S);
    return OK;
}

Status visit_read(SElemType e)
{
    printf("%d ", e);
    return OK;
}

顺序队列

声明过程

#include "constants.h"

#define MAXQSIZE 100

typedef int QElemType;

typedef struct
{
    QElemType *base; //存储空间基地址
    int front;       //队头指针,指向队头元素
    int rear;        //队尾指针,指向队尾元素的下一个位置
} SqQueue;

Status InitQueue(SqQueue &Q);//初始化一个顺序空队列

Status QueueEmpty(SqQueue Q);//判断该顺序队列是否为空

int QueueLength(SqQueue Q);//返回顺序队列的长度

Status GetHead(SqQueue Q, QElemType &e);//得到队头元素,并用e带回

Status EnQueue(SqQueue &Q, QElemType e);//入队

Status DeQueue(SqQueue &Q, QElemType &e);//出队

Status ClearQueue(SqQueue &Q);//清空队列

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType));//遍历队列

Status DestroyQueue(SqQueue &Q);//销毁队列

Status Visit(QElemType e);

实现过程

#include "SqQueue.h"
#include <stdlib.h>
#include <stdio.h>

Status InitQueue(SqQueue &Q)
{
    Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base)
        exit(OVERFLOW);
    Q.front = Q.rear = 0;
    return OK;
}

Status QueueEmpty(SqQueue Q)
{
    return Q.rear == Q.front;
}

int QueueLength(SqQueue Q)
{
    return Q.rear - Q.front;
}

Status GetHead(SqQueue Q, QElemType &e)
{
    e = Q.base[Q.front];
    return OK;
}

Status EnQueue(SqQueue &Q, QElemType e)
{
    Q.base[Q.rear++] = e;
    return OK;
}

Status DeQueue(SqQueue &Q, QElemType &e)
{
    e = Q.base[Q.front++];
    return OK;
}

Status ClearQueue(SqQueue &Q)
{
    Q.front = Q.rear = 0;
    return OK;
}

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType))
{
    int i;
    for (i = Q.front; i < Q.rear; i++)
        if (!Visit(Q.base[i]))
            return ERROR;
    return OK;
}

Status DestroyQueue(SqQueue &Q)
{
    free(Q.base);
    return OK;
}

Status Visit(QElemType e)
{
    printf("%d ", e);
    return OK;
}

循环队列

假若循环队列的实现与顺序队列相同的话,那么在队列判空和判满时,条件相同,出现矛盾。为了解决这个问题,共有三种方案。

声明过程 

#include "constants.h"

#define MAXQSIZE 100

typedef int QElemType;

typedef struct
{
    QElemType *base; //存储空间基地址
    int front;       //队头指针,指向队头元素
    int rear;        //队尾指针,指向队尾元素的下一个位置
} SqQueue;

Status InitQueue(SqQueue &Q);//初始化一个顺序空队列

Status QueueEmpty1(SqQueue Q);//判断该顺序队列是否为空

int QueueLength(SqQueue Q);//返回顺序队列的长度

Status GetHead(SqQueue Q, QElemType &e);//得到队头元素,并用e带回

Status EnQueue(SqQueue &Q, QElemType e);//入队

Status DeQueue(SqQueue &Q, QElemType &e);//出队

Status ClearQueue(SqQueue &Q);//清空队列

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType));//遍历队列

Status DestroyQueue(SqQueue &Q);//销毁队列

Status Visit(QElemType e);

Status QueueFull(SqQueue Q);//判断队列是否已满

实现过程

//方案一
#include "CSqQueue.h"
#include <stdio.h>
#include <stdlib.h>

Status InitQueue(SqQueue &Q)
{
    Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base)
        exit(OVERFLOW);
    Q.front = Q.rear = 0;
    return OK;
}

int QueueLength(SqQueue Q)
{
    return (Q.rear + MAXQSIZE - Q.front) % MAXQSIZE;
}

//基地址所指向的空间不存储数据
Status QueueEmpty1(SqQueue Q)
{
    return Q.front == Q.rear;
}

Status GetHead(SqQueue Q, QElemType &e)
{
    if (QueueEmpty1(Q))
        return ERROR;
    else
    {
        e = Q.base[Q.front];
        return OK;
    }
}

Status EnQueue(SqQueue &Q, QElemType e)
{
    if (QueueFull(Q))
        return ERROR;
    else
    {
        Q.base[Q.rear] = e;
        Q.rear = (Q.rear + 1) % MAXQSIZE;
        return OK;
    }
}

Status DeQueue(SqQueue &Q, QElemType &e)
{
    if (QueueEmpty1(Q))
        return ERROR;
    else
    {
        e = Q.base[Q.front];
        Q.front = (Q.front + 1) % MAXQSIZE;
        return OK;
    }
}

Status ClearQueue(SqQueue &Q)
{
    Q.front = Q.rear;
    return OK;
}

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType))
{
    int i = Q.front;
    while (i != Q.rear)
    {
        if (Visit(Q.base[i]))
            i = (i + 1) % MAXQSIZE;
        else
            return ERROR;
    }
    return OK;
}

/* free函数与malloc函数配对使用,释放malloc函数申请的动态内存。
对于free(p)这句语句,如果p时空指针,那么free对p无论操作多少次都不会出问题;
如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。 */
Status DestroyQueue(SqQueue &Q)
{
    if (Q.base)
        free(Q.base);
    Q.base = NULL;
    return OK;
}

Status Visit(QElemType e)
{
    printf("%d ", e);
    return OK;
}

Status QueueFull(SqQueue Q)
{
    return Q.front == (Q.rear + 1) % MAXQSIZE;
}
//方案二
#include "CSqQueue.h"
#include <stdlib.h>
#include <stdio.h>

Status InitQueue(SqQueue &Q)
{
    Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base)
        exit(OVERFLOW);
    Q.front = Q.rear = 0;
    Q.tag = 0;
    return OK;
}

Status QueueEmpty2(SqQueue Q)
{
    return Q.front == Q.rear && Q.tag == 0;
}

int QueueLength(SqQueue Q)
{
    return (Q.rear + MAXQSIZE - Q.front) % MAXQSIZE;
}

Status GetHead(SqQueue Q, QElemType &e)
{
    if (QueueEmpty2(Q))
        return ERROR;
    e = Q.base[Q.front];
    return OK;
}

Status EnQueue(SqQueue &Q, QElemType e)
{
    if (QueueFull(Q))
        return ERROR;
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear + 1) % MAXQSIZE;
    Q.tag = 1;
    return OK;
}

Status DeQueue(SqQueue &Q, QElemType &e)
{
    if (QueueEmpty2(Q))
        return ERROR;
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    Q.tag = 0;
    return OK;
}

Status ClearQueue(SqQueue &Q)
{
    Q.rear = Q.front;
    return OK;
}

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType))
{
    int i = Q.front;
    while (i != Q.rear)
    {
        if (Visit(Q.base[i]))
            i = (i + 1) % MAXQSIZE;
        else
            return ERROR;
    }
    return OK;
}

Status DestroyQueue(SqQueue &Q)
{
    if (!Q.base)
        free(Q.base);
    Q.base = NULL;
    return OK;
}

Status Visit(QElemType e)
{
    printf("%d ", e);
    return OK;
}

Status QueueFull(SqQueue Q)
{
    return Q.front == Q.rear && Q.tag == 1;
}
//方案三
#include "CSqQueue.h"
#include <stdio.h>
#include <stdlib.h>

Status InitQueue(SqQueue &Q)
{
    Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
    if (!Q.base)
        exit(OVERFLOW);
    Q.front = 0;
    Q.length = 0;
    return OK;
}

Status QueueEmpty3(SqQueue Q)
{
    return Q.length == 0;
}

int QueueLength(SqQueue Q)
{
    return Q.length;
}

Status GetHead(SqQueue Q, QElemType &e)
{
    if (QueueEmpty3(Q))
        return ERROR;
    e = Q.base[Q.front];
    return OK;
}

Status EnQueue(SqQueue &Q, QElemType e)
{
    if (QueueFull(Q))
        return ERROR;
    Q.base[Q.front] = e;
    Q.front = (Q.front + 1) % MAXQSIZE;
    Q.length++;
    return OK;
}

Status DeQueue(SqQueue &Q, QElemType &e)
{
    if (QueueEmpty3(Q))
        return ERROR;
    e = Q.base[Q.front + Q.length - 1];
    Q.length--;
    return OK;
}

Status ClearQueue(SqQueue &Q)
{
    Q.length = 0;
    return OK;
}

Status QueueTraverse(SqQueue Q, Status (*Visit)(QElemType))
{
    int sign = Q.front;
    for (int i = 0; i < Q.length; i++)
    {
        if (Visit(Q.base[sign]))
            sign = (sign + 1) % MAXQSIZE;
        else
            return ERROR;
    }
    return OK;
}

Status DestroyQueue(SqQueue &Q)
{
    if (!Q.base)
        free(Q.base);
    Q.base = NULL;
    return OK;
}

Status Visit(QElemType e)
{
    printf("%d ", e);
    return OK;
}

Status QueueFull(SqQueue Q)
{
    return Q.length == MAXQSIZE;
}

链式队列

声明过程

//若无法估计所使用队列的长度,则使用链队列
#include "constants.h"

typedef int QElemType;

typedef struct QNode
{
    QElemType data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct
{
    QueuePtr front;//指向链式队列的头结点(链式队列的头结点的指针域指向队头结点)
    QueuePtr rear;//指向链式队列的尾结点
} LinkQueue;

Status InitQueue(LinkQueue &Q);//初始化一个空链队列

Status QueueEmpty(LinkQueue Q);//判断链队列是否为空

int QueueLength(LinkQueue Q);//返回链队列的长度

Status GetHead(LinkQueue Q, QElemType &e);//得到链队列的队头元素,并且用e来返回

Status EnQueue(LinkQueue &Q, QElemType e);//入队

Status DeQueue(LinkQueue &Q, QElemType &e);//出队

Status ClearQueue(LinkQueue &Q);//清空链队列

Status QueueTraverse(LinkQueue Q, Status (*Visit)(QElemType));//遍历链队列

Status DestroyQueue(LinkQueue &Q);//销毁链队列

Status visit(QElemType e);//读取函数

实现过程

#include "LinkQueue.h"
#include <stdlib.h>
#include <stdio.h>

Status InitQueue(LinkQueue &Q)
{
    Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
    if (!Q.front)
        exit(OVERFLOW);
    Q.front->next = NULL;
    return OK;
}

Status QueueEmpty(LinkQueue Q)
{
    return Q.front == Q.rear;
}

int QueueLength(LinkQueue Q)
{
    int len = 0;
    QueuePtr p = Q.front->next;
    while (p)
    {
        len++;
        p = p->next;
    }
    return len;
}

Status GetHead(LinkQueue Q, QElemType &e)
{
    if (QueueEmpty(Q))
        return ERROR;
    e = Q.front->next->data;
    return OK;
}

//当链式队列中有新结点加入时,我们要记得更新队列尾结点指针
Status EnQueue(LinkQueue &Q, QElemType e)
{
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if (!p)
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
    return OK;
}

//如果出队的结点是队尾结点,那么在出队操作前,需要更新队尾指针,让其等于队头指针,即均指向头结点
Status DeQueue(LinkQueue &Q, QElemType &e)
{
    if (QueueEmpty(Q))
        return ERROR;
    QueuePtr p = Q.front->next->next;
    e = Q.front->next->data;
    if (Q.front->next == Q.rear)
        Q.rear = Q.front;
    free(Q.front->next);
    Q.front->next = p;
    return OK;
}

Status ClearQueue(LinkQueue &Q)
{
    Q.front = Q.rear;
    return OK;
}

Status QueueTraverse(LinkQueue Q, Status (*Visit)(QElemType))
{
    QueuePtr p = Q.front->next;
    while (p)
    {
        Visit(p->data);
        p = p->next;
    }
    return OK;
}

Status DestroyQueue(LinkQueue &Q)
{
    if (Q.front)
        free(Q.front);
    Q.front = NULL;
    return OK;
}

Status visit(QElemType e)
{
    printf("%d ", e);
    return OK;
}

上一篇:图搜索算法


下一篇:移远EC200S模块连接搭建在阿里云服务器的FTP服务器的过程