数据结构考试要求-第三章 栈和队列

第三章 栈和队列

顺序栈

需了解栈的基本的先进后出或后进先出模型,分为栈顶和栈底

数组栈和链式栈

两种线性结构的栈实现都可以,数组栈结构稍微好一点

链式结构栈
  • 如果用尾做栈顶,尾插尾删,要设计成双向链表,否则删除数据效率会很低
  • 如果用头做栈顶,头插头删,就可以设计成单链表

栈的实现

结构体
typedef int STDataType;
typedef struct Stack {
    STDataType* a;
    int top;
    int capacity;
}ST;
实现操作
void StackInit(ST * ps);                // 初始化
void StackDestroy(ST * ps);             // 销毁
void StackPush(ST * ps, STDataType x);  // 进栈
void StackPop(ST* ps);                  // 出栈
STDataType StackTop(ST* ps);            // 栈顶元素
int StackSize(ST* ps);                  // 栈的长度
bool StackEmpty(ST* ps);                // 判空
初始化
void StackInit(ST * ps) {
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
销毁
void StackDestroy(ST * ps) {
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->top = ps->capacity = 0;
}
进栈
void StackPush(ST * ps, STDataType x) {
    assert(ps);
    if (ps->top == ps->capacity) {
        int newCapacity = ps->capacity == 0 ? 4 : ps->capacity *2;
        STDataType * tmp = realloc(ps->a, sizeof(STDataType)*newCapacity);
        if (tmp == NULL) {
            printf("realloc fail");
            exit(-1);
        }
        ps->a = tmp;
        ps->capacity = newCapacity;
    }
    ps->a[ps->top] = x;
    ps->top++;
}
出栈
void StackPop(ST* ps) {
    assert(ps);
    assert(!StackEmpty(ps));
    ps->top--;
}
查找栈顶元素
STDataType StackTop(ST* ps) {
    assert(ps);
    assert(!StackEmpty(ps));
    return ps->a[ps->top - 1];
}
查询栈顶长度
int StackSize(ST* ps) {
    assert(ps);
    return ps->top;
}
栈的判空
bool StackEmpty(ST* ps) {
    assert(ps);
    return ps->top == 0;
}

队列

只允许在一端进行插入操作,在另一端进行删除操作,先进先出
入队列:进行插入的一端,做为队尾
出数据:进行删除的一端,作为队头

队列的实现

用链表实现较容易

结构体
typedef int QDataType;

typedef struct QueueNode {
    struct QueueNode* next;
    QDataType data;
}QNode;

typedef struct Queue {
    QNode * head;
    QNode * tail;
}Queue;
实现操作
void QueueInit(Queue* pq);                  // 初始化
void QueueDestroy(Queue* pq);               // 销毁操作
void QueuePush(Queue* pq, QDataType x);     // 进队列
void QueuePop(Queue* pq);                   // 出队列
QDataType QueueFront(Queue* pq);            // 队头
QDataType QueueBack(Queue* pq);             // 队尾
int QueueSize(Queue* pq);                   // 队列的长度
bool QueueEmpty(Queue* pq);                 // 队列的判空
具体实现
void QueueInit(Queue* pq) {
    assert(pq);
    pq->head = NULL;
    pq->tail = NULL;
}
void QueueDestroy(Queue* pq) {
    assert(pq);
    QNode * cur = pq->head;
    while (cur != NULL) {
        QNode * next = cur->next;
        free(cur);
        cur = next;
    }
    pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x) {
    assert(pq);
    QNode * newNode = (QNode*)malloc(sizeof(QNode));
    newNode->data = x;
    if (pq->head == NULL) {
        pq->head = pq->tail = newNode;
    } else {
        pq->tail->next = newNode;
        pq->tail = newNode;
    }

}
void QueuePop(Queue* pq) {
    assert(pq);
    assert(!QueueEmpty(pq));
    pq->head = pq->head->next;
    free(pq->head);
    if (pq->head == NULL) {
        pq->tail = NULL;
    }


}
QDataType QueueFront(Queue* pq) {
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->head->data;
}
QDataType QueueBack(Queue* pq) {
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->tail->data;
}
int QueueSize(Queue* pq) {
    assert(pq);
    int n = 0;
    QNode *cur = pq->head;
    while (cur) {
        ++n;
        cur = cur->next;
    }
    return n;
}
bool QueueEmpty(Queue* pq) {
    assert(pq);
    return pq->head == NULL;
}

设计循环队列

操作表现基于先进先出原则,并且队尾连接在队首以后形成一个循环,也被称为“环形缓冲器”
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有i空间。但是使用循环队列,我们能使用这些空间去存储新的值。
基于以上描述,实现循环队列固定长度为k,则需申请k+1个空间

  • 符合先进先出
  • 空间大小固定
循环队列的判空和判满
顺序表

front == tail 为空
(tail+1) %(k+1)== front 为满

循环链表

front == tail 为空
tail->next == front

循环队列实现
#include 
#include 
#include 
typedef int QNodeType;
typedef struct CircularQueue {
    QNodeType * a;
    int front;
    int tail;
    int k;
}CQueue;

bool CQueueIsFull(CQueue *pQueue);
bool CQueueIsEmpty(CQueue* pcq);

CQueue * CQueueCreate(int k) {
    CQueue* cq = (CQueue*)malloc(sizeof(CQueue));
    cq->front = cq->tail = 0;
    cq->a = (QNodeType*)malloc(sizeof(QNodeType)*(k + 1));
    cq->k = k;
    return cq;
}

bool CQueueEnQueue(CQueue* pcq, QNodeType x) {
    if (CQueueIsFull(pcq)) {
        return false;
    }
    pcq->a[pcq->tail] = x;
    ++pcq->tail;
    pcq->tail %= (pcq->k+1);
    return true;

}

bool CQueueIsFull(CQueue* pcq) {
    return (pcq->tail + 1) % (pcq->k + 1) == pcq->front;
}

bool CQueueIsEmpty(CQueue* pcq) {
    return pcq->front == pcq->tail;
}

bool CQueueFree(CQueue* pcq) {
    free(pcq->a);
    free(pcq);
}

bool CQueueDeQueue(CQueue* pcq) {
    if (CQueueIsEmpty(pcq)) {
        return false;
    }
    ++pcq->front;
    pcq->front %= (pcq->k + 1);
    return true;
}

QNodeType CQueueFront(CQueue* pcq) {
    if (CQueueIsEmpty(pcq)) {
        return -1;
    }
    return pcq->a[pcq->front];
}

QNodeType CQueueRear(CQueue* pcq) {
    if (CQueueIsEmpty(pcq)) {
        return -1;
    }
    if (pcq->tail == 0) {
        return pcq->a[pcq->k];
    } else {
        return pcq->a[pcq->tail - 1];
    }
}

第三章-串,数组,广义表

你可能感兴趣的:(数据结构,链表,算法)