zoukankan      html  css  js  c++  java
  • 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

    请按任意键继续. . .

  • 相关阅读:
    vscode已有64位版本。
    git代码回滚的两种选择
    代码维护的问题
    草珊瑚理解IFC(inline formatting context)
    nodejs的dependency.md
    如何实现在H5里调起高德地图APP?(下)
    如何实现在H5里调起高德地图APP?(上)
    酸奶妈妈再次回归~
    【从零开始学】如何在安卓平台上实现定位?
    如何将四大名著和地图相结合?
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7250519.html
Copyright © 2011-2022 走看看