C语言数据结构——栈的顺序存储

一、栈的基本概念

栈是一种特殊的线性表,也就是说栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里插入是指栈顶,而不是栈底。
栈只能在线性表的一端进行操作
栈顶(Top):允许操作的一端
栈底(Bottom):不允许操作的一端
栈的插入操作,叫做进栈,也称压栈、入栈。
栈的删除操作,叫做出栈,也有的叫做弹栈。在这里插入图片描述

二、栈的顺序存储

1.基本概念

在这里插入图片描述

2.设计方法

<1>先在头文件内声明我们想实现的方法

header.h

//
// Created by 2NaCl on 2019/2/25.
//

#ifndef CPRIMERPLUS_HEADER_H
#define CPRIMERPLUS_HEADER_H

typedef void SeqStack;

SeqStack *SeqStack_Create(int capacity);

void SeqStack_Destroy(SeqStack *stack);

void SeqStack_Clear(SeqStack *stack);

int SeqStack_Push(SeqStack *stack,void *item);

void *SeqStack_Pop(SeqStack *stack);

void *SeqStack_Top(SeqStack *stack);

int SeqStack_Size(SeqStack *stack);

int SeqStack_Capacity(SeqStack *stack);

#endif //CPRIMERPLUS_HEADER_H

<2>在main.c中将声明的方法带入实现

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "header.h"
int main(){

    int ret;
    int a[10];
    SeqStack *stack = NULL;
    stack = SeqStack_Create(10);
    if (stack == NULL){
        printf("建表出错了");
    }

    for (int i = 0; i < 5; ++i) {
        a[i]=i+1;
        SeqStack_Push(stack, &a[i]);
        printf("Bottom:%d\n", SeqStack_Size(stack));
    }
    printf("Capacity:%d\n", SeqStack_Capacity(stack));
    printf("Length:%d\n", SeqStack_Size(stack));

    while(SeqStack_Size(stack)>0) {
        int tmp =*((int *)SeqStack_Pop(stack));
        printf("删除了%d", tmp);
    }

    system("pause");
}

<3>将SeqList的header.h与SeqStack的header.h进行整合

SeqList.header.h

typedef void SeqList;//声明一下线性表
typedef void SeqListNode;//声明组成结点的结构体

SeqList *seqList_Create(int capacity);//创建一张线性表

void SeqList_Destroy(SeqList *list);//销毁一张线性表

void SeqList_Clear(SeqList *list);//清空结点元素

int SeqList_Length(SeqList *list);//返回线性表的长度

int SeqList_Insert(SeqList *list,SeqListNode *node,int pos);//向SeqList链表pos的位置插入一个结点node

SeqListNode *list_Get(SeqList *list , int pos);//获取pos位置元素

SeqListNode *list_Delete(SeqList *list,int pos);//删除pos位置元素

<4>将SeqList的SeqList.c与SeqStack的SeqStack.c进行整合

SeqList.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"

typedef struct SeqList{
    int length;//链表实际长度
    int capacity;//分配最大的容量
    unsigned int *node;//所有的结点所形成的数组
    // (动态库内的结点,有多少分配多少,是动态的,所以要用指针指向内存空间内的结点)
}tSeqList;

SeqList *seqList_Create(int capacity){
    tSeqList *tmp = NULL;//既可以在栈分配内存空间,也可以在堆分配内存空间,但是让初始的链表为空
    tmp = (tSeqList *) malloc(sizeof(tSeqList));
    if(tmp ==NULL) {
        printf("func SeqList_Create error:%d",0);
        return NULL;
    }

    memset(tmp, 0, sizeof(tSeqList));//总的作用:将已开辟内存空间tmp的首sizeof(tSeqList)个字节的值设为值0


// 根据capacity分配结点空间
    tmp->node = (unsigned int *) malloc(sizeof(unsigned int *) * capacity);
    if (tmp->node == NULL) {
        printf("func SeqList_Create error:%d",0);
        return NULL;
    }
    tmp->capacity = capacity;
    tmp->length = 0;
    return tmp;

}

void SeqList_Destroy(SeqList *list){
    tSeqList *tList = NULL;
    if (list == NULL) {
        return;
    }
    tList = (tSeqList *) list;
    if (tList->node != NULL) {
        free(tList->node);
    }
    free(tList);
}

//清空链表
void SeqList_Clear(SeqList *list){
    tSeqList *tList = NULL;
    if (list == NULL) {
        return;
    }
    tList = (tSeqList *) list;
    tList->length = 0;
}

//求链表长度
int SeqList_Length(SeqList *list){
    tSeqList *tList = NULL;
    if (list == NULL) {
        return 0;
    }
    tList = (tSeqList *) list;
    return tList->length;
}



int SeqList_Insert(SeqList *list,SeqListNode *node,int pos){
    int ret = 0;
    tSeqList *tList = NULL;
    if (list == NULL || node == NULL || pos < 0) {
        return ret;
    }
    tList = (tSeqList *) list;
    //判断插入元素是否满了
    if (tList->length == tList->capacity) {
        printf("满了");
    }
// 容错修正,pos>length
    if (pos > tList->length) {
        pos = tList->length;
    }
    //1.元素后移
    int i = 0;
    for (i = (*tList).length; i > pos; --i) {
        tList->node[i] = (*tList).node[i - 1];
    }
    //2.插入元素
    tList->node[i] = (unsigned int) node;
    tList->length++;
}

SeqListNode *list_Get(SeqList *list , int pos){
    int i = 0;
    SeqListNode *ret = 0;
    tSeqList *tList = NULL;
    if (list == NULL || pos < 0) {
        printf("产生了错误");
        return NULL;
    }
    tList = (tSeqList *) list;
    ret = (void *)tList->node[pos];
    return ret;
}

SeqListNode *list_Delete(SeqList *list,int pos){
    SeqListNode *ret = 0;
    tSeqList *tList = NULL;
    if (list == NULL || pos < 0) {
        printf("产生了错误");
        return NULL;
    }
    tList = (tSeqList *) list;
    ret = (SeqListNode *) tList->node[pos];
    for (int i = pos+1; i <tList->length; ++i) {
        tList->node[i - 1] = tList->node[i];
    }
    tList->length--;
    return ret;
}

SeqStack.c

#include "header.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//创建栈,相当于创建线性表
SeqStack *SeqStack_Create(int capacity){
    return seqList_Create(capacity);
}

//毁灭栈,相当于销毁线性表
void SeqStack_Destroy(SeqStack *stack){
    SeqList_Destroy(stack);
}

//清空栈,相当于清空线性表
void SeqStack_Clear(SeqStack *stack){
    SeqList_Clear(stack);
}

//Insert
int SeqStack_Push(SeqStack *stack,void *item){//因为要向尾部插入元素,所以插入的位置pos=stack.length
    SeqList_Insert(stack, item, SeqList_Length(stack));
}

//Delete
void *SeqStack_Pop(SeqStack *stack){//弄出来
    list_Delete(stack, SeqList_Length(stack)-1);
}

//栈顶
void *SeqStack_Top(SeqStack *stack){//检测栈顶
    return list_Get(stack, SeqList_Length(stack)-1);
}

int SeqStack_Size(SeqStack *stack){
    return SeqList_Length(stack);

}

int SeqStack_Capacity(SeqStack *stack){//Capacity
    return SeqList_Capacity(stack);
}

3.优点和缺点

优点:在数据查找(特别是不按照规律排列的数据),时间复杂度教少.效率高. 缺点:插入删除需要移动大量的元素,无法确定内存容量