数据结构笔记-栈与队列

数据结构笔记

栈与队列

学习问题

基本概念

限定性线性表

操作受限的线性表。

栈(Stack)

只能在同一端进行插入和删除操作的线性表。

允许插入和删除的一端称为栈顶(Top),另一端称为栈底(Bottom),没有元素称为空栈

元素插入被称为入栈,元素删除被称为退栈

由于后进先出的特性也被称为LIFO(Last In First Out)表。

ADT定义

ADT Stack{

​ 数据元素:只要求性质相同

​ 结构关系:线性

​ 运算集合:

​ (1) initStack(S)

​ 操作前提:栈S已存在

​ 操作结果:

​ (2)clearStack(S)

​ 操作前提:栈S已存在

​ 操作结果:

​ (3)isFull(S)

​ 操作前提:栈S已存在

​ 操作结果:

​ (4)push(S,e)

​ 操作前提:栈S已存在

​ 操作结果:

​ (5)pop(S)

​ 操作前提:栈S已存在

​ 操作结果:

​ (6)getTop(S)

​ 操作前提:栈S已存在

​ 操作结果:

}Stack;

队列(Queue)

只允许在一端插入元素,在另一端删除元素的线性表。

其中,允许插入的一端称为队尾,允许删除的一端称为队头

由于先进先出的特性也被称为FIFO(Last In First Out)表。

ADT定义

ADT Queue{

​ 数据元素:只要求性质相同

​ 结构关系:线性

​ 运算集合:

​ (1) initQueue(Q)

​ 操作前提:队列Q已存在

​ 操作结果:

​ (2)clearQueue(Q)

​ 操作前提:队列Q已存在

​ 操作结果:

​ (3)isFull(Q)

​ 操作前提:队列Q已存在

​ 操作结果:

​ (4)enterQueue(Q,e)

​ 操作前提:队列Q已存在

​ 操作结果:

​ (5)deleteQueue(Q)

​ 操作前提:队列Q已存在

​ 操作结果:

​ (6)getHead(Q)

​ 操作前提:队列Q已存在

​ 操作结果:

}Queue;

实现

顺序栈

//
//  Stack.h
//  Data structure
//  顺序栈
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#ifndef Stack_h
    #define Stack_h
    #define STACK_SIZE 50

    #include <stdio.h>
    #include <stdbool.h>
    
struct Stack{
    int elem[STACK_SIZE];
    int top;
};
typedef struct Stack Stack;

void initStack(Stack *);
void clearStack(Stack *);
_Bool isFull(Stack *);
_Bool isEmpty(Stack *);
void push(Stack *,int);
void pop(Stack *);
int getTop(Stack *);

#endif /* Stack_h */

//
//  Stack.c
//  Data structure
//  顺序栈
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#include "Stack.h"

void initStack(Stack * stack){
    if (!stack) {
        printf("\nThe stack is NULL");
        return;
    }
    
    stack->top = -1;
}

void clearStack(Stack * stack){
    if (!stack) {
        printf("\nThe stack is NULL");
        return;
    }
    
    for (int top = stack->top; top > -1; top--) {
        pop(stack);
    }
}

_Bool isFull(Stack * stack){
    if (!stack) {
        printf("\nThe stack is NULL");
        return false;
    }
    
    if (stack->top == STACK_SIZE - 1) {
        return true;
    }else{
        return false;
    }
}

_Bool isEmpty(Stack * stack){
    if (!stack) {
        printf("\nThe stack is NULL");
        return false;
    }
    
    if (stack->top == -1) {
        return true;
    }else{
        return false;
    }
}

void push(Stack * stack,int e){
    if (!stack) {
       printf("\nThe stack is NULL");
       return;
    }
    
    if (isFull(stack)) {
        printf("The stack is full.Can not push!\n");
        return;
    }
    
    stack->top++;
    stack->elem[stack->top] = e;
}

void pop(Stack * stack){
    if (!stack) {
        printf("The stack is NULL\n");
        return;
    }
    
    if (isEmpty(stack)) {
        printf("The stack is empty.Can not pop!\n");
        return;
    }
    
    stack->top--;
}

int getTop(Stack * stack){
    if (!stack) {
       printf("\nThe stack is NULL");
       return -1;
    }
    
    if (isEmpty(stack)) {
        printf("\nThe stack is empty");
        return -1;
    }
    return stack->elem[stack->top];
}
//测试
void testStack(void){
    Stack s,* stack;
    stack = &s;
    initStack(stack);
    push(stack, 1);
    printf("%d\n",getTop(stack));
    printf("stack length is %d\n",stack->top + 1);
    printf("stack is full?%s\n",isFull(stack)?"true":"false");
    for (int top = 2; top < 11; top++) {
        push(stack, top);
    }
    printf("stack is full?%s\n",isFull(stack)?"true":"false");
    
    for (int top = 1; top < 11; top++) {
        printf("%d  ",getTop(stack));
        pop(stack);
    }
    printf("\n");
    pop(stack);
    
    for (int top = 1; top <= 50; top++) {
        push(stack, top);
    }
    push(stack, 51);
    
    printf("\n");
}

ALL OUTPUT:
1
stack length is 1
stack is full?false
stack is full?false
10  9  8  7  6  5  4  3  2  1  
The stack is empty.Can not pop!
The stack is full.Can not push!

Program ended with exit code: 0

双端顺序栈

//
//  DStack.h
//  Data structure
//  双端栈
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#ifndef DStack_h
    #define DStack_h
    #define DSTACK_SIZE 100
    #include <stdio.h>
    #include <stdbool.h>

struct DStack{
    int elem[DSTACK_SIZE];
    int top[2];
};
typedef struct DStack DStack;

void initStack_ds(DStack *);
void clearStack_ds(DStack *);
_Bool isFull_ds(DStack *);
_Bool isEmpty_ds(DStack *);
void push_ds(DStack *,int,int);
void pop_ds(DStack *,int);
int getTop_ds(DStack *,int);

#endif /* DStack_h */

//
//  DStack.c
//  Data structure
//  双端栈
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#include "DStack.h"

void initStack_ds(DStack * dStack){
    dStack->top[0] = -1;
    dStack->top[1] = DSTACK_SIZE;
}

void clearStack_ds(DStack * dStack){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return;
    }
    
    dStack->top[0] = -1;
    dStack->top[1] = DSTACK_SIZE;
}

_Bool isFull_ds(DStack * dStack){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return false;
    }
    
    if (dStack->top[0] - dStack->top[1] == -1) {
        return true;
    }else{
        return false;
    }
}
_Bool isEmpty_ds(DStack * dStack){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return false;
    }
    
    if (dStack->top[0] == -1 && dStack->top[1] == DSTACK_SIZE) {
        return true;
    }else{
        return false;
    }
}

void push_ds(DStack * dStack,int i,int e){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return ;
    }
    
    if (isFull(dStack)) {
        printf("\nThe stack is full");
        return ;
    }
    switch (i) {
        case 0:
            dStack->top[0]++;
            dStack->elem[dStack->top[0]] = e;
            break;
        case 1:
            dStack->top[1]--;
            dStack->elem[dStack->top[1]] = e;
            
        default:
            printf("\nThe sub stack is not exist");
            break;
    }
}

void pop_ds(DStack * dStack,int i){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return ;
    }
    
    switch (i) {
        case 0:
            dStack->top[0]--;
            break;
        case 1:
            dStack->top[1]++;
        default:
            break;
    }
}

int getTop_ds(DStack * dStack,int i){
    if (!dStack) {
        printf("\nThe stack is NULL");
        return -1;
    }
    
    switch (i) {
        case 0:
            if (dStack->top[0] == -1) {
                printf("The sub stack is empty");
                return -1;
            }else{
                return dStack->elem[dStack->top[0]];
            }
        case 1:
            if (dStack->top[1] == DSTACK_SIZE) {
                printf("The sub stack is empty");
                return -1;
            }else{
                return dStack->elem[dStack->top[1]];
            }
        default:
            return -1;
            break;
    }
}

链栈

//
//  LinkStack.h
//  Data structure
//  链栈
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#ifndef LinkStack_h
#define LinkStack_h

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct LsNode{
    int data;
    struct LsNode * next;
};

typedef struct LsNode LsNode;

LsNode * initStack_ls(LsNode *);
void clearStack_ls(LsNode *);
_Bool isFull_ls(LsNode *);
_Bool isEmpty_ls(LsNode *);
void push_ls(LsNode *,int);
void pop_ls(LsNode *);
int getTop_ls(LsNode *);

#endif /* LinkStack_h */

//
//  LinkStack.c
//  Data structure
//
//  Created by 樊明杨 on 2020/3/2.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#include "LinkStack.h"

LsNode * initStack_ls(LsNode * linkStack){
    linkStack = (LsNode *)malloc(sizeof(LsNode));
    linkStack->data = 0;
    linkStack->next = NULL;
    
    return linkStack;
}

void clearStack_ls(LsNode * linkStack){
    if (linkStack == NULL) {
        printf("\nThe link stack is null");
        return ;
    }
    
    if (isEmpty(linkStack)) {
        printf("\nThe link stack is empty");
        return ;
    }
    
    for (int top = linkStack->data; top > 0 ; top--) {
        pop(linkStack);
    }
}

_Bool isFull_ls(LsNode * linkStack){
    return false;
}

_Bool isEmpty_ls(LsNode * linkStack){
    if (linkStack == NULL) {
        printf("\nThe link stack is null");
        return false;
    }
    
    if (linkStack->data == 0) {
        return true;
    }else{
        return false;
    }
}

void push_ls(LsNode * linkStack,int e){
    if (linkStack == NULL) {
        printf("\nThe link stack is null");
        return ;
    }
    
    LsNode * newNode = (LsNode *)malloc(sizeof(LsNode));
    newNode->data = e;
    newNode->next = linkStack->next;
    linkStack->next = newNode;
    linkStack->data++;
}

void pop_ls(LsNode * linkStack){
    if (linkStack == NULL) {
        printf("\nThe link stack is null");
        return ;
    }
    
    if (isEmpty(linkStack)) {
        printf("\nThe link stack is empty");
        return ;
    }
    
    LsNode * deleteNode = linkStack->next;
    linkStack->next = deleteNode->next;
    free(deleteNode);
    linkStack->data--;
}

int getTop_ls(LsNode * linkStack){
    if (linkStack == NULL) {
        printf("\nThe link stack is null");
        return -1;
    }
    
    if (isEmpty(linkStack)) {
        printf("\nThe link stack is empty");
        return -1;
    }
    
    return linkStack->next->data;
}

链队

//
//  LinkQueue.h
//  Data structure
//	链队
//  Created by 樊明杨 on 2020/3/4.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#ifndef LinkQueue_h
#define LinkQueue_h

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct LinkQueueNode{
    int data;
    struct LinkQueueNode * next;
};
typedef struct LinkQueueNode LinkQueueNode;

struct LinkQueue{
    LinkQueueNode * front;
    LinkQueueNode * rear;
};

typedef struct LinkQueue LinkQueue;

void initQueue(LinkQueue *);
void clearQueue(LinkQueue *);
_Bool isFull_queue(LinkQueue *);
_Bool isEmpty_queue(LinkQueue *);
void enterQueue(LinkQueue *,int);
void deleteQueue(LinkQueue *);
int getHead(LinkQueue *);

#endif /* LinkQueue_h */
//
//  LinkQueue.c
//  Data structure
//  链队
//  Created by 樊明杨 on 2020/3/4.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#include "LinkQueue.h"

void initQueue(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return;
    }
    
    queue->front = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
    if (!queue->front) {
        printf("The stack overflow!\n");
        exit(0);
    }else{
        queue->rear = queue->front;
        queue->front->data = 0;
        queue->front->next = NULL;
    }
}

void clearQueue(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return;
    }
    
    if (isEmpty_queue(queue)) {
        printf("The queue is empty\n");
        return;
    }
    
    for (int head = 1; head <= queue->front->data; head++) {
        deleteQueue(queue);
    }
}

_Bool isFull_queue(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return true;
    }
    return false;
}

_Bool isEmpty_queue(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return true;
    }
    
    if (queue->front->data == 0) {
        return true;
    }else{
        return false;
    }
}

void enterQueue(LinkQueue * queue,int e){
    if (!queue) {
        printf("The queue is NULL\n");
        return ;
    }
    
    LinkQueueNode * newNode = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
    if (!newNode) {
        printf("The stack overflow!\n");
        exit(0);
    }
    newNode->data = e;
    newNode->next = NULL;
    
    queue->rear->next = newNode;
    queue->rear = newNode;
    queue->front->data++;
}

void deleteQueue(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return ;
    }
    
    if (isEmpty_queue(queue)) {
        printf("The queue is empty\n");
        return;
    }
    
    LinkQueueNode * deleteNode = queue->front->next;
    queue->front->next = deleteNode->next;
    free(deleteNode);
    queue->front->data--;
}

int getHead(LinkQueue * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if (isEmpty_queue(queue)) {
        printf("The queue is empty\n");
        exit(0);
    }
    
    return queue->front->next->data;
}
//测试
void testLinkQueue(void){
    LinkQueue q,* queue;
    queue = &q;
    initQueue(queue);
    printf("The queue is empty? %s\n",isEmpty_queue(queue)?"true":"false");
    
    for (int rear = 0; rear < 10; rear++) {
        enterQueue(queue, rear + 1);
    }
    
    printf("The head elem is %d\n",getHead(queue));
    int queueSize = queue->front->data;
    for (int front = 1; front <= queueSize; front++) {
        printf("The length of queue is %d.Get head elem %d.Delete the elem.\n",queue->front->data,getHead(queue));
        deleteQueue(queue);
    }
    deleteQueue(queue);
    printf("The queue is empty? %s\n",isEmpty_queue(queue)?"true":"false");
    printf("The length of queue is %d\n",queue->front->data);
}

ALL OUTPUT:
The queue is empty? true
The head elem is 1
The length of queue is 10.Get head elem 1.Delete the elem.
The length of queue is 9.Get head elem 2.Delete the elem.
The length of queue is 8.Get head elem 3.Delete the elem.
The length of queue is 7.Get head elem 4.Delete the elem.
The length of queue is 6.Get head elem 5.Delete the elem.
The length of queue is 5.Get head elem 6.Delete the elem.
The length of queue is 4.Get head elem 7.Delete the elem.
The length of queue is 3.Get head elem 8.Delete the elem.
The length of queue is 2.Get head elem 9.Delete the elem.
The length of queue is 1.Get head elem 10.Delete the elem.
The queue is empty
The queue is empty? true
The length of queue is 0
Program ended with exit code: 0

循环队列

顺序队列用数组存储数据元素,同样包含两个指针,首元(队头)指针front和队尾指针rear。初始时,二者都指向位置0。当插入元素的时候,rear后移1位,front不动。所以,表非空时rear指向最后一个元素的后一位。当删除元素的时候,front后移一位,rear不动。

因此,这样的结构容易造成假溢出的问题,即当队头指针front与队尾指针rear重合的时候队头之前还有剩余没有利用的存储空间。

对于用数组存储元素的结构,其元素编号是从0到MAX_SIZE-1。我们的指针也维持在这个数值范围。

循环队列指循环顺序队列,当rear处于MAX_SIZE-1的位置时,若还有剩余空间,就让rear指向位置0。这里涉及到一个问题,即如何用数学表达式表示指针的移动后的正确位置。答案是:
( r e a r + 1 ) m o d    M A X _ S I Z E (rear + 1) \mod MAX\_SIZE
这样的话就会遇到另外一个问题,即如何判断表是否满了。因为rear可能会追上front。解决方案包括:

  • 废弃"表尾"元素。即当rear指向的空单元的后继单元如果是队头元素的话,就认为表满了。
  • 设置"队满"的标识。比如:初始化时设置tag=0,队满时设置tag=1。

这里采用第一种方案处理。

//
//  CSeqQueue.h
//  Data structure
//  循环队列
//  Created by 樊明杨 on 2020/3/4.
//  Copyright © 2020 樊明杨. All rights reserved.
//

#ifndef CSeqQueue_h
    #define CSeqQueue_h

    #ifndef MAX_SIZE
    #define MAX_SIZE 10
    #endif

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

struct CSeqNode{
    int queue[MAX_SIZE];
    int front,rear;
};
typedef struct CSeqNode CSeqNode;

void initQueue_csq(CSeqNode *);
void clearQueue_csq(CSeqNode *);
_Bool isFull_csq(CSeqNode *);
_Bool isEmpty_csq(CSeqNode *);
void enterQueue_csq(CSeqNode *,int);
void deleteQueue_csq(CSeqNode *);
int getHead_csq(CSeqNode *);

#endif /* CSeqQueue_h */
//
//  CSeqQueue.c
//  Data structure
//  循环队列
//  Created by 樊明杨 on 2020/3/4.
//  Copyright © 2020 樊明杨. All rights reserved.
//  front指针直接指向第一个结点(首元结点),没有头结点。
//  rear指针指向最后一个元素后面地那个结点。
//  判断表是否满了的策略是:损失表最后一个结点,即在头指针与尾指针之间必须保留一个空的元素。

#include "CSeqQueue.h"

void initQueue_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return;
    }
    
    queue->front = 0;
    queue->rear = 0;
}

void clearQueue_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        return;
    }
    
    while (!isEmpty_csq(queue)) {
        deleteQueue_csq(queue);
    }
}

_Bool isFull_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if ((queue->rear + 1) % MAX_SIZE == queue->front) {
        return true;
    }else{
        return false;
    }
}

_Bool isEmpty_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if (queue->front == queue->rear) {
        return true;
    }else{
        return false;
    }
}

void enterQueue_csq(CSeqNode * queue,int e){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if (isFull_csq(queue)) {
        printf("The queue is full.Can not enter queue.The front is %d,the rear is %d.\n",queue->front,queue->rear);
    }else{
        queue->queue[queue->rear] = e;
        queue->rear = (queue->rear + 1) % MAX_SIZE;
        printf("Enqueue : front is %d,rear is %d\n",queue->front,queue->rear);
    }
}

void deleteQueue_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if (isEmpty_csq(queue)) {
        printf("The queue is empty.Can not delete queue.\n");
    }else{
        queue->front = (queue->front + 1) % MAX_SIZE;
        printf("Delete : front is %d,rear is %d\n",queue->front,queue->rear);
    }
}

int getHead_csq(CSeqNode * queue){
    if (!queue) {
        printf("The queue is NULL\n");
        exit(0);
    }
    
    if (isEmpty_csq(queue)) {
        printf("The queue is empty.Can not delete queue.\n");
        exit(0);
    }else{
        return queue->queue[queue->front];
    }
}
//测试
//先测了顺序插入10个元素,检查第10个元素是否拒绝插入和每次插入之后的指针是否正确。再依次遍历并删除所有元素,
//检查指针是否正确。重新插入10个元素,检查第10个元素是否拒绝插入和每次插入之后的指针是否正确。然后,删除第1个
//元素并检查front指针是否正确,再插入1个元素并检查rear指针是否正确。最后,依次遍历并删除所有元素,检查指针是
//否正确。
void testCSeqQueue(void){
    CSeqNode node,* queue;
    queue = &node;
    
    initQueue_csq(queue);
    printf("The queue is empty? %s\n",isEmpty_csq(queue)?"true":"false");
    
    for (int front = 0; front < 10; front++) {
        enterQueue_csq(queue, front + 1);
    }
    printf("The queue is full? %s\n",isFull_csq(queue)?"true":"false");
    
    while (!isEmpty_csq(queue)) {
        printf("Get head elem %d.Delete the elem.\n",getHead_csq(queue));
        deleteQueue_csq(queue);
    }
    printf("front is %d,rear is %d\n",queue->front,queue->rear);
    printf("The queue is empty? %s\n",isEmpty_csq(queue)?"true":"false");
    for (int front = 0; front < 10; front++) {
        enterQueue_csq(queue, front + 1);
    }
    deleteQueue_csq(queue);
    enterQueue_csq(queue, 1);
    while (!isEmpty_csq(queue)) {
        printf("Get head elem %d.Delete the elem.\n",getHead_csq(queue));
        deleteQueue_csq(queue);
    }
}

ALL OUTPUT:
The queue is empty? true
Enqueue : front is 0,rear is 1
Enqueue : front is 0,rear is 2
Enqueue : front is 0,rear is 3
Enqueue : front is 0,rear is 4
Enqueue : front is 0,rear is 5
Enqueue : front is 0,rear is 6
Enqueue : front is 0,rear is 7
Enqueue : front is 0,rear is 8
Enqueue : front is 0,rear is 9
The queue is full.Can not enter queue.The front is 0,the rear is 9.
The queue is full? true
Get head elem 1.Delete the elem.
Delete : front is 1,rear is 9
Get head elem 2.Delete the elem.
Delete : front is 2,rear is 9
Get head elem 3.Delete the elem.
Delete : front is 3,rear is 9
Get head elem 4.Delete the elem.
Delete : front is 4,rear is 9
Get head elem 5.Delete the elem.
Delete : front is 5,rear is 9
Get head elem 6.Delete the elem.
Delete : front is 6,rear is 9
Get head elem 7.Delete the elem.
Delete : front is 7,rear is 9
Get head elem 8.Delete the elem.
Delete : front is 8,rear is 9
Get head elem 9.Delete the elem.
Delete : front is 9,rear is 9
front is 9,rear is 9
The queue is empty? true
Enqueue : front is 9,rear is 0
Enqueue : front is 9,rear is 1
Enqueue : front is 9,rear is 2
Enqueue : front is 9,rear is 3
Enqueue : front is 9,rear is 4
Enqueue : front is 9,rear is 5
Enqueue : front is 9,rear is 6
Enqueue : front is 9,rear is 7
Enqueue : front is 9,rear is 8
The queue is full.Can not enter queue.The front is 9,the rear is 8.
Delete : front is 0,rear is 8
Enqueue : front is 0,rear is 9
Get head elem 2.Delete the elem.
Delete : front is 1,rear is 9
Get head elem 3.Delete the elem.
Delete : front is 2,rear is 9
Get head elem 4.Delete the elem.
Delete : front is 3,rear is 9
Get head elem 5.Delete the elem.
Delete : front is 4,rear is 9
Get head elem 6.Delete the elem.
Delete : front is 5,rear is 9
Get head elem 7.Delete the elem.
Delete : front is 6,rear is 9
Get head elem 8.Delete the elem.
Delete : front is 7,rear is 9
Get head elem 9.Delete the elem.
Delete : front is 8,rear is 9
Get head elem 1.Delete the elem.
Delete : front is 9,rear is 9
Program ended with exit code: 0

性能分析

时间性能

不论栈还是队列,每次都只能从一端操作元素。

  • 插入、删除和修改操作的渐进时间复杂度都是O(1),空间复杂度也是O(1)。
  • 若想要查找某个位置元素的值就必须先删除排在其后面或前面的元素。从这个意义上说,其渐进时间复杂度是O(n)

选择栈还是队列要根据实际问题的需求。

空间性能

栈或队列顺序存储,事先申请了一片连续的存储空间,这个空间的大小难以准确估计,过高则造成浪费,过低则可能造成上溢。其每一个结点都只包含一个数据域,存储密度为1,若不考虑备用结点占用的存储空间,则其空间利用率为100%。

栈或队列链式存储,在程序运行时动态地申请内存空间来存储结点数据。只要系统内存可用,就不会面临上溢的问题,即不受表长度变化的影响。其每一个结点不仅包含一个数据域还包含1或多个指针域,存储密度小于1,其空间利用率小于100%。

因此,若表长变化大则选择链式存储,若要节约存储空间则选择顺序存储。

应用

栈可以被操作系统暂时保存,因此可以优先处理最新的栈,再处理次新的栈。这种机制可以解决元素的保存次序与使用次序相反的问题,比如:递归问题和进制间转换。

队列也可以控制解决问题的顺序,凡是要求元素的保存次序与使用次序相同的问题,都可以用队列解决,比如:键盘缓冲区问题。

发布了14 篇原创文章 · 获赞 0 · 访问量 726

猜你喜欢

转载自blog.csdn.net/qq_38878217/article/details/104737337