4.栈

一.stack基本概念

栈是一种  特殊的线性表

栈仅能在线性表的一端进行操作

栈顶(Top):允许操作的一端

栈底(Bottom):不允许操作的一端

stack常用操作

  • 创建栈
  • 销毁栈
  • 清空栈
  • 进栈
  • 出栈
  • 获取栈顶元素
  • 获取栈的大小

二.栈的顺序存储设计与实现

2.1 基本概念

2.2 代码实现

栈是一种特殊的线性表,因此可以使用线性表的顺序存储结构予以实现:

seqlist.h

#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_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_Capacity(SeqList* list);

// 向线性表插入元素
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

// 获取线性表元素
SeqListNode* SeqList_Get(SeqList* list, int pos);

// 删除线性表中指定元素
SeqListNode* SeqList_Delete(SeqList* list, int pos);


#endif

seqlist.c

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

#include "seqlist.h"


typedef struct _tag_SeqList
{
    int capacity;
    int length;
    unsigned int *arr;
}TSeqList;



// 创建线性表
SeqList* SeqList_Create(int capacity)
{
    TSeqList *ret = NULL;
    if (capacity <= 0) return NULL;

    ret = (TSeqList*)malloc(sizeof(TSeqList)+sizeof(unsigned int)*capacity);
    if (ret != NULL)
    {
        memset(ret, 0, sizeof(sizeof(TSeqList)+sizeof(unsigned int)*capacity));
        ret->capacity = capacity;
        ret->length = 0;
        ret->arr = (unsigned int *)(ret + 1);
    }
    return ret;
}



// 销毁线性表
void SeqList_Destroy(SeqList* list)
{
    if (list != NULL) free(list);
}


// 清空线性表
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 -1;
    tList = (TSeqList*)list;
    return tList->length;
}


// 获取当前线性表容量
int SeqList_Capacity(SeqList* list)
{
    TSeqList *tList = NULL;
    if (list == NULL) return -1;
    tList = (TSeqList*)list;
    return tList->capacity;
}


// 向线性表插入元素
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
    TSeqList *tList = NULL;
    int i = 0;
    if (list == NULL || node == NULL || pos < 0) return -1;
    tList = (TSeqList*)list;

    if (tList->length >= tList->capacity) return -2;
    if (pos >= tList->capacity) return -3;
    if (pos >= tList->length) pos = tList->length;

    // 插入算法
    for (i = tList->length; i>pos; i--)
    {
        // 把前面的元素向后移
        tList->arr[i] = tList->arr[i-1];
    }
    tList->arr[pos] = (unsigned int)node;                    // 将传入的指针使用16进制整数保存
    tList->length++;

    return 1;
}


// 获取线性表元素
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
    TSeqList *tList = NULL;
    SeqListNode *ret = NULL;
    if (list == NULL || pos < 0) return NULL;
    tList = (TSeqList*)list;

    ret = (SeqListNode*)tList->arr[pos];
    return ret;
}


// 删除线性表中指定元素
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
    SeqListNode *ret = NULL;
    TSeqList *tList = NULL;
    int i = 0;

    if (list == NULL || pos < 0) return NULL;
    tList = (TSeqList*)list;
    if (pos >= tList->length) return NULL;
    
    // 记录待删除的元素
    ret = (SeqListNode*)tList->arr[pos];
    // 删除算法
    for (i = pos + 1; i < tList->length; i++)
    {
        tList->arr[i - 1] = tList->arr[i];
    }
    tList->length--;
    return ret;
}

seqstack.h

#ifndef __MY_SEQSTACK_H__
#define __MY_SEQSTACK_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

seqstack.c

#include "seqstack.h"
#include "seqlist.h"


// 创建栈
SeqStack* SeqStack_Create(int capacity)
{
    return SeqList_Create(capacity);
}

// 销毁栈
void SeqStack_Destroy(SeqStack *stack)
{
    return SeqList_Destroy(stack);
}


// 清空栈
void SeqStack_Clear(SeqStack *stack)
{
    SeqList_Clear(stack);
}


// 将元素压入栈底,相当于向线性表中插入元素(尾插法)
int SeqStack_Push(SeqStack *stack, void *item)
{
    return SeqList_Insert(stack, item, SeqList_Length(stack));
}


// 弹出栈顶元素,相当于从线性表中删除元素,即:删除最后一个元素
void* SeqStack_Pop(SeqStack *stack)
{
    return SeqList_Delete(stack, SeqList_Length(stack) - 1);
}


// 获取当前栈顶元素
void* SeqStack_Top(SeqStack *stack)
{
    return SeqList_Get(stack, SeqList_Length(stack) - 1);
}


// 获取当前栈的大小
int SeqStack_Size(SeqStack *stack)
{
    return SeqList_Length(stack);
}


// 获取当前栈的容量
int    SeqStack_Capacity(SeqStack *stack)
{
    return SeqList_Capacity(stack);
}

test.c

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


typedef struct _Student
{
    char name[64];
    int age;
}Student;


int main()
{

    int a[20], i = 0;
    SeqStack *stack = NULL;

    stack = SeqStack_Create(20);
    
    
    if (stack != NULL)
    {
        for (i = 0; i < 10; i++)
        {
            a[i] = i + 1;
            SeqStack_Push(stack, a + i);
        }


        // 获取栈顶元素
        int *pTop = (int*)SeqStack_Top(stack);
        printf("current top value is: %d
", *pTop);
        printf("
");

        printf("current stack capacity is: %d
",SeqStack_Capacity(stack));
        printf("
");

        printf("current stack size is: %d
",SeqStack_Size(stack));

        // 弹出栈顶元素
        SeqStack_Pop(stack);
        int *top = (int*)SeqStack_Top(stack);
        printf("current top valus is: %d
",*top);

        // 销毁栈
        SeqStack_Destroy(stack);

    }

    system("pause");
    return 0;
}

运行结果:

current top value is: 10

current stack capacity is: 20

current stack size is: 10
current top valus is: 9
请按任意键继续. . .

三.栈的链式存储设计与实现

3.1 基本概念

3.2 代码实现

linklist.h

#ifndef __MY_LINKLIST_H__
#define __MY_LINKLIST_H__

#define DLL_API  __declspec(dllexport)    //_declspec(dllexport):导出标志

typedef void LinkList;

typedef struct _tag_LinkListNode
{
    struct _tag_LinkListNode* next;      // 当前节点需要指向下一个节点的地址
}LinkListNode;




LinkList* LinkList_Create();

void LinkList_Destroy(LinkList *list);

void LinkList_Clear(LinkList *list);

int LinkList_Length(LinkList *list);

int LinkList_Insert(LinkList *list, LinkListNode *node, int pos);

LinkListNode* LinkList_Get(LinkList *list, int pos);

LinkListNode* ListList_Delete(LinkList *list, int pos);


#endif

linklist.c

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


typedef struct _tag_LinkList
{
    LinkListNode header;              //  链表中需要包含一个头节点
    int length;
}TLinkList;


// 创建链表
LinkList* LinkList_Create()
{
    TLinkList *ret = (TLinkList*)malloc(sizeof(TLinkList));
    if (ret == NULL) return NULL;
    memset(ret, 0, sizeof(TLinkList));

    ret->header.next = NULL;
    ret->length = 0;
    return ret;
}


// 销毁链表
void LinkList_Destroy(LinkList *list)
{
    if (list != NULL)
    {
        free(list);
    }
}


// 清空链表
void LinkList_Clear(LinkList *list)
{
    TLinkList *tList = NULL;
    if (list == NULL) return;
    
    tList = (TLinkList*)list;
    tList->header.next = NULL;
    tList->length = 0;
}


// 获取当前链表长度
int LinkList_Length(LinkList *list)
{
    TLinkList *tList = NULL;
    if (list == NULL) return -1;
    tList = (TLinkList*)list;

    return tList->length;
}


// 向当前链表插入数据
int LinkList_Insert(LinkList *list, LinkListNode *node, int pos)
{
    TLinkList *tList = NULL;
    LinkListNode *current = NULL;
    int i = 0;

    tList = (TLinkList*)list;

    // 过滤非法参数
    if (list == NULL || pos < 0)
    {
        return -1;
    }

    /* 
     * 插入要点
     *1.让新插入的元素节点指向原有位置的元素节点
     *2.修改原有位置的前一个元素节点的指向(更新指向为新插入的元素节点)
     */

    // 准备环境让辅助指针变量 指向链表头节点
    current = &tList->header;
    // 将当前链表的节点移动到待插入节点的前一个节点的位置(假如待插入的位置是3,则移动到2号位置)
    for (i = 0; i < pos && (current->next != NULL); i++)
    {
        current = current->next; // 将辅助节点运动到指定位置(待插入位置的前一个节点)
    }
    // 让新插入的元素节点指向原有位置的元素节点
    node->next = current->next;
    current->next = node;
    tList->length++;

    return 0;
}

LinkListNode* LinkList_Get(LinkList *list, int pos)
{
    TLinkList *tList = NULL;
    int i = 0;
    LinkListNode *current = NULL;
    LinkListNode *ret = NULL;


    tList = (TLinkList *)list;
    // 过滤非法参数
    if (list == NULL || pos < 0 || pos >= tList->length)
    {
        return NULL;
    }

    
    current = &tList->header;
    // 将辅助指针变量运行到待获取元素的前一个节点
    for (i = 0; i < pos && (current->next != NULL); i++)
    {
        current = current->next;
    }

    ret = current->next;
    return ret;
}




LinkListNode* ListList_Delete(LinkList *list, int pos)
{

    TLinkList *tList = NULL;
    tList = (TLinkList *)list;
    LinkListNode *current = NULL;
    LinkListNode *ret = NULL;
    int i = 0;

    // 过滤非法参数
    if (list == NULL || pos < 0 || pos >= tList->length)
    {
        return NULL;
    }

    // 移动辅助指针变量
    current = &tList->header;
    for (i = 0; i < pos && (current->next != NULL); i++)
    {
        current = current->next;
    }
    ret = current->next;
    
    // 将待删除位置的前一个节点的指向连接到删除位置节点的指向
    current->next = ret->next;
    // 将链表长度-1
    tList->length--;

    return ret;
}

linkstack.h

#ifndef __MY_LINKSTACK_H__
#define __MY_LINKSTACK_H__

typedef void LinkStack;


// 创建栈
LinkStack* LinkStack_Create();

// 销毁栈
void LinkStack_Destroy(LinkStack* stack);

// 清空栈
void LinkStack_Clear(LinkStack* stack);

// 将元素压入栈
int LinkStack_Push(LinkStack* stack, void* item);

// 弹出栈顶元素
void*  LinkStack_Pop(LinkStack* stack);

// 返回栈顶元素
void* LinkStack_Top(LinkStack* stack);

// 返回元素个数
int LinkStack_Size(LinkStack* stack);



#endif

linkstack.c

#include <stdlib.h>

#include "linkstack.h"
#include "linklist.h"


// 占位结构 与node节点大小一样
typedef struct _tag_LinkStackNode
{
    LinkListNode node;
    void *item;
}TLinkStackNode;


// 创建栈
LinkStack* LinkStack_Create()
{
    return LinkList_Create();
}


// 销毁栈(注意destroy的时候,需要把栈中的所有元素都清空)
void LinkStack_Destroy(LinkStack* stack)
{
    if (stack == NULL) return;
    LinkStack_Clear(stack); // 释放内存
    LinkList_Destroy(stack);
}


// 清空栈
void LinkStack_Clear(LinkStack* stack)
{
    if (stack == NULL) return;
    while (LinkStack_Size(stack) > 0)
    {
        LinkStack_Pop(stack); // 这个函数中有内存释放函数
    }
}


// 将元素压入栈
int LinkStack_Push(LinkStack* stack, void* item)
{
    int ret = 0;
    TLinkStackNode *pTe = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
    if (pTe == NULL) return -1;
    pTe->item = item;

    // 头插法,向线性表中插入元素,插入元素的时候需要构造业务节点,采用头插法,保证先进后出
    ret = LinkList_Insert(stack, (LinkListNode*)pTe, 0);
    if (ret != 0) // 插入失败
    {
        free(pTe);
    }
    return ret;
}



// 弹出栈顶元素
void* LinkStack_Pop(LinkStack* stack)
{

    void *ret = NULL;
    TLinkStackNode *pTmp = NULL;
    pTmp = (TLinkStackNode*)ListList_Delete(stack, 0);
    if (pTmp == NULL) return NULL;

    ret = pTmp->item;
    free(pTmp);

    return ret;
}

// 返回栈顶元素
void* LinkStack_Top(LinkStack* stack)
{
    void *ret = NULL;
    TLinkStackNode *tmp = NULL;
    tmp = (TLinkStackNode*)LinkList_Get(stack, 0);
    if (tmp == NULL) return NULL;
    ret = tmp->item;
    return ret;
}

// 返回元素个数
int LinkStack_Size(LinkStack* stack)
{
    return LinkList_Length(stack);
}

test.c

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

#include "linkstack.h"


typedef struct _Student{
    char name[64];
    int age;
}Student;




int main()
{
    

    Student s1;
    Student s2;
    Student s3;
    Student s4;
    Student s5;
    Student s6;


    s1.age = 11;
    s2.age = 12;
    s3.age = 13;
    s4.age = 14;
    s5.age = 15;
    s6.age = 16;


    LinkStack *stack = LinkStack_Create();
    if (stack != NULL)
    {
        
        // 压栈
        LinkStack_Push(stack, &s1);
        LinkStack_Push(stack, &s2);
        LinkStack_Push(stack, &s3);


        printf("current stack size is: %d
",LinkStack_Size(stack));
        printf("
");
        
        // 栈顶元素
        Student *pStu = NULL;
        pStu = LinkStack_Top(stack);
        printf("current stack element is %d
",pStu->age);
        printf("
");

        // 弹出栈顶元素
        LinkStack_Pop(stack);
        pStu = LinkStack_Top(stack);
        printf("current stack element is %d
", pStu->age);
        printf("
");

        // 清空栈
        LinkStack_Clear(stack);
        printf("current stack size is: %d
",LinkStack_Size(stack));
        printf("
");

        // 销毁栈
        LinkStack_Destroy(stack);

    }



    system("pause");
    return 0;
}

运行结果:

current stack size is: 3

current stack element is 13

current stack element is 12

current stack size is: 0

请按任意键继续. . .

原文地址:https://www.cnblogs.com/yongdaimi/p/7250519.html