链表实现的数据结构栈及相关函数

一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操
作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。不含任
何元素的栈称为空栈,栈又称为后进先出的线性表。

分类

由于站结构是一种线性结构,所以它的实现方式也有很多种,最常见的是链表和顺序表实现的栈结构,本篇介绍的是基于带头节点双向单链表栈结构
链式栈
话不多说,上代码

LinkStack.h

#pragma once
// 基于带头节点双向单链表栈

#include <stdlib.h>
#include <stddef.h>
#include <errno.h>

#define Datatype char

// 与基于顺序表的栈相比,链表栈长度不定,每次建立节点
typedef struct LinkStack {
    Datatype data;
    struct LinkStack* next;
    struct LinkStack* prev;
} LinkStack;

// 栈初始化为空栈
void LinkStackInit(LinkStack* head);

// 栈销毁
void LinkStackDestroy(LinkStack* head);

// 入栈
void LinkStackPush(LinkStack* head, Datatype value);

// 出栈
void LinkStackPop(LinkStack* head);

// 取栈顶元素, 输出型参数value用来接收栈顶的值,函数返回值返回函数是否是执行成功
int LinkStackTop(LinkStack* head, Datatype* value);

LinkStack.c

#include "LinkStack.h"

// 创建节点
LinkStack* Creat(Datatype value) {
    LinkStack* node = malloc(sizeof(LinkStack));
    node->data = value;
    return node;
}
// 销毁节点
void Destroy(LinkStack* node) {
    free(node);
}

// 栈初始化为空栈
void LinkStackInit(LinkStack* head) {
    // 非法输入
    if(head == NULL) {
        perror("LinkStackInit");
        return;
    }
    head->next = head;
    head->prev = head;
}

// 栈销毁
void LinkStackDestroy(LinkStack* head) {
    // 非法输入
    if(head == NULL) {
        perror("Destroy");
        return;
    }
    // 空栈
    if(head->next == NULL) {
        return; 
    }
    LinkStack* cur = head->next;
    while(head != NULL) {
        LinkStack* tmp = cur;
        cur = cur->next;
        Destroy(tmp);
    }
}

// 入栈,尾插
void LinkStackPush(LinkStack* head, Datatype value) {
    // 非法输入
    if(head == NULL) {
        perror("push");
        return;
    }
    // 创建新节点
    LinkStack* new_node = Creat(value);
    LinkStack* tail = head->prev;

    new_node->next = head;
    head->prev = new_node;
    new_node->prev = tail;
    tail->next = new_node;
}

// 出栈,尾删
void LinkStackPop(LinkStack* head) {
    // 非法输入
    if(head == NULL) {
        perror("push");
        return;
    }
    // 空栈
    if(head->next == head) {
        return;
    }
    LinkStack* tail_prev = head->prev->prev;    
    LinkStack* tmp = head->prev;
    tail_prev->next = head;
    head->prev = tail_prev;
    Destroy(tmp);
}

// 取栈顶元素, 输出型参数value用来接收栈顶的值,函数返回值返回函数是否是执行成功
int LinkStackTop(LinkStack* head, Datatype* value) {
    // 非法输入
    if(head == NULL) {
        perror("top");
        value = NULL;
        return 0;
    }
    // 空栈
    if(head->next == head) {
        value = NULL;
        return 0;
    }
    *value = head->prev->data;
    return 1; 
}


/* *********************************************
 * ******************* test ********************
 * *********************************************/

#if 1
#include <stdio.h>

#define FUNCTION() printf("\n==================== %s ====================\n", __FUNCTION__);

// 链表打印函数
void print(LinkStack* head, const char* msg) {
    printf("%s\n", msg);
    // 空链表
    if(head->next == NULL) {
        printf("空链表\n");
        return;
    }
    printf("%s\n", msg);
    // 正序打印
    printf("正序:\n");
    LinkStack* cur = head->next;
    while(cur != head) {
        printf("[%c | %p] ", cur->data, cur);
        cur = cur->next;
    }
    // 倒序打印
    printf("\n倒序:\n");
    cur = head->prev;
    while(cur != head) {
        printf("[%c | %p] ", cur->data, cur);
        cur = cur->prev;
    }
    printf("\n");

    // 打印栈
    printf("栈顶\n");
    cur = head->prev;
    while(cur != head) {
        printf("[%c | %p]\n", cur->data, cur);
        cur = cur->prev;
    }

    printf("栈底\n");


}

// 入栈测试
void TestPush() {
    FUNCTION();
    LinkStack* head = Creat(0);
    LinkStackInit(head);

    LinkStackPush(head, 'a');
    LinkStackPush(head, 'b');
    LinkStackPush(head, 'c');
    LinkStackPush(head, 'd');
    print(head, "入栈四个");
}

// 出栈测试
void TestPop() {
    FUNCTION();
    LinkStack* head = Creat(0);
    LinkStackInit(head);

    LinkStackPush(head, 'a');
    LinkStackPush(head, 'b');
    LinkStackPush(head, 'c');
    LinkStackPush(head, 'd');
    print(head, "入栈四个");

    LinkStackPop(head);
    print(head, "出栈一个");
    LinkStackPop(head);
    print(head, "出栈两个");
    LinkStackPop(head);
    print(head, "出栈三个");
    LinkStackPop(head);
    print(head, "出栈四个");
    LinkStackPop(head);
    print(head, "空栈出栈");
}

// 取栈顶元素测试
void TestTop() {
    FUNCTION();
    LinkStack* head = Creat(0);
    LinkStackInit(head);

    LinkStackPush(head, 'a');
    LinkStackPush(head, 'b');
    LinkStackPush(head, 'c');
    LinkStackPush(head, 'd');
    print(head, "入栈四个");

    Datatype value = 0;
    int ret = LinkStackTop(head, &value);
    printf("ret is %d, value is %c\n", ret, value);
}



int main() {
    TestPush();
    TestPop();
    TestTop();
}
#endif

本篇包含代码是现在CentOS6.5
如有错误,请斧正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值