栈练习之Example003-用不带头结点的单链表存储链栈并实现栈相关算法

Example003

题目

用不带头结点的单链表存储链栈,设计初始化栈、判断栈是否为空、进栈和出栈等相应的算法。

分析

不带头结点的单链表 list 为空的条件是 list==NULL,进栈和出栈操作都是在表头进行的。

在入栈的时候,由于没有头结点,所以空栈和非空栈的入栈操作需要分情况处理。

图解

不带头结点的空栈和非空栈如图所示:

在这里插入图片描述

入栈,如果是空栈则如下图所示:

在这里插入图片描述

入栈,如果是非空栈则如下图所示:

在这里插入图片描述

出栈,操作如图所示:

在这里插入图片描述

C实现

完整代码:

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

/**
 * 栈结点结构体定义
 */
typedef struct LNode {
    /**
     * 结点数据域
     */
    int data;
    /**
     * 结点指针域,指向后继结点
     */
    struct LNode *next;
} LNode;

/**
 * 初始化不带头结点的链栈
 * @param stack 未初始化的链栈
 */
void init(LNode **stack) {
    // 即置为 NULL,没有头结点
    *stack = NULL;
}

/**
 * 判断链栈是否为空
 * @param stack 不带头结点的链栈
 * @return 如果链栈为空则返回 1,否则返回 0 表示非空
 */
int isEmpty(LNode *stack) {
    if (stack == NULL) {
        return 1;
    } else {
        return 0;
    }
}

/**
 * 将元素入栈。注意,链栈不需要校验栈是否满的问题
 * @param stack 不带头结点的链栈
 * @param ele 元素值
 */
void push(LNode **stack, int ele) {
    // 1.创建新结点并为其指定数据域和初始化指针域
    LNode *newNode = (LNode *) malloc(sizeof(LNode));
    newNode->data = ele;
    newNode->next = NULL;

    // 2.但需要判断栈是否为空的问题,如果栈为空,则新结点是链栈的第一个结点;如果栈非空,则新结点成为链栈新的栈顶结点
    if (stack == NULL) {
        // 新结点直接称为栈顶结点
        *stack = newNode;
    } else {
        // 将新结点入栈
        newNode->next = *stack;
        *stack = newNode;
    }
}

/**
 * 将元素出栈
 * @param stack 不带头结点的链栈
 * @param ele 用来存储出栈元素的值
 * @return 如果栈空则返回 0 表示出栈失败,否则返回 1 表示出栈成功
 */
int pop(LNode **stack, int *ele) {
    // 1.需要校验是否是空栈
    if (*stack == NULL) {
        return 0;
    }
    // 2.将元素出栈
    LNode *node = *stack;
    // 2.1 用 ele 保存出栈元素的数据值
    *ele = node->data;
    // 2.2 删除栈顶结点
    *stack = node->next;
    // 2.3 释放结点空间
    free(node);
    // 2.4 返回 1 表示出栈成功
    return 1;
}

/**
 * 获取栈顶元素,但不出栈
 * @param stack 不带头结点的链栈
 * @param ele 用来存储出栈元素的值
 * @return 如果栈空则返回 0 表示出栈失败,否则返回 1 表示出栈成功
 */
int getTop(LNode *stack, int *ele) {
    // 1.如果栈空则返回 0 表示获取失败
    if (stack == NULL) {
        return 0;
    }
    // 2.用 ele 保存栈顶元素值
    *ele = stack->data;
    return 1;
}

/**
 * 获取链栈中结点个数
 * @param stack 不带头结点的链栈
 * @return 结点个数
 */
int size(LNode *stack) {
    // 变量,记录链栈结点个数
    int len = 0;
    // 从栈顶到栈底扫描链栈所有结点,统计个数
    while (stack != NULL) {
        len++;
        stack = stack->next;
    }
    return len;
}

/**
 * 打印链栈所有结点
 * @param stack 不带头结点的链栈
 */
void print(LNode *stack) {
    printf("[");
    while (stack != NULL) {
        printf("%d", stack->data);
        if (stack->next != NULL) {
            printf(", ");
        }
        stack = stack->next;
    }
    printf("]\n");
}

/**
 * 清空链栈
 * @param stack 不带头结点的链栈
 */
void clear(LNode **stack) {
    // 释放链栈中每一个结点的空间
    while (*stack != NULL) {
        LNode *node = (*stack)->next;
        free(*stack);
        *stack = node;
    }
    *stack = NULL;
}

/**
 * 销毁链栈
 * @param stack 不带头结点的链栈
 */
void destroy(LNode **stack) {
    free(*stack);
}

int main() {
    // 声明链栈
    LNode *stack;

    // 初始化链栈
    printf("初始化链栈:\n");
    init(&stack);
    print(stack);

    // 将元素入栈
    printf("将元素入栈:\n");
    push(&stack, 11);
    print(stack);
    push(&stack, 22);
    print(stack);
    push(&stack, 33);
    print(stack);
    push(&stack, 44);
    print(stack);
    push(&stack, 55);
    print(stack);

    // 将元素出栈
    printf("将元素出栈:\n");
    int ele;
    pop(&stack, &ele);
    print(stack);
    pop(&stack, &ele);
    print(stack);
    pop(&stack, &ele);
    print(stack);

    // 链栈是否为空
    printf("链栈是否为空:\n");
    int empty;
    empty = isEmpty(stack);
    printf("%d\n", empty);

    // 获取栈顶结点数据
    printf("获取栈顶结点数据:\n");
    int top;
    getTop(stack, &top);
    printf("%d\n", top);

    // 获取链栈中元素个数
    printf("获取链栈中元素个数:\n");
    int len;
    len = size(stack);
    printf("%d\n", len);

    // 清空链栈
    printf("清空链栈:\n");
    clear(&stack);
    print(stack);

    // 销毁链栈
    printf("销毁链栈:\n");
    destroy(&stack);
}

执行结果:

初始化链栈:
[]
将元素入栈:
[11]
[22, 11]
[33, 22, 11]
[44, 33, 22, 11]
[55, 44, 33, 22, 11]
将元素出栈:
[44, 33, 22, 11]
[33, 22, 11]
[22, 11]
链栈是否为空:
0
获取栈顶结点数据:
22
获取链栈中元素个数:
2
清空链栈:
[]
销毁链栈:

Java实现

完整代码:

public class LinkedStack {
    /**
     * 声明不带头结点的链栈
     */
    private LNode stack;

    /**
     * 初始化没有头结点的链栈
     */
    public void init() {
        // 即指向 null 表示空栈
        stack = null;
    }

    /**
     * 判断链栈是否为空
     *
     * @return 如果链栈为空则返回 true,否则返回 false 表示非空
     */
    public boolean isEmpty() {
        // 即判断头指针是否指向 null
        return stack == null;
    }

    /**
     * 将元素入栈
     *
     * @param ele 待入栈的元素值
     */
    public void push(int ele) {
        // 1.如果是空栈,则将新结点置为链栈的栈顶结点
        if (stack == null) {
            // 直接是栈顶结点
            stack = new LNode();
            stack.data = ele;
            stack.next = null;
        }
        // 2.如果是非空栈,则创建新结点并且将新结点与原链栈连接起来
        else {
            // 2.1 创建新结点并为其分配数据域和指针域
            LNode newNode = new LNode();
            newNode.data = ele;
            newNode.next = null;
            // 2.2 将新结点与原链栈连接起来,成为新的链栈栈顶结点
            newNode.next = stack;
            stack = newNode;
        }
    }

    /**
     * 将栈顶元素出栈
     *
     * @return 栈顶元素值
     * @throws Exception 如果栈空则抛出此异常
     */
    public int pop() throws Exception {
        // 0.参数校验,如果栈空则抛出异常
        if (stack == null) {
            throw new Exception("栈空,没有元素可出栈!");
        }
        // 1.出栈栈顶元素
        // 1.1 记录栈顶结点的值然后返回
        int top = stack.data;
        // 1.2 删除栈顶结点,让原栈顶结点的后继结点成为新的栈顶结点
        stack = stack.next;
        return top;
    }

    /**
     * 获取栈顶结点的值
     *
     * @return 栈顶结点的数据值
     * @throws Exception 如果栈空则抛出此异常
     */
    public int getTop() throws Exception {
        // 0.参数校验,如果栈空则抛出异常
        if (stack == null) {
            throw new Exception("栈空,没有元素可出栈!");
        }
        // 1.直接返回栈顶结点的数据值
        return stack.data;
    }

    /**
     * 获取链栈中的结点个数
     *
     * @return 链栈的结点个数
     */
    public int size() {
        // 变量,记录链栈结点个数
        int len = 0;
        // 变量,记录链栈,为了不修改链栈本身
        LNode node = stack;
        while (node != null) {
            len++;
            node = node.next;
        }
        return len;
    }

    /**
     * 打印链栈所有结点
     */
    public void print() {
        LNode node = stack;
        System.out.print("[");
        while (node != null) {
            System.out.print(node.data);
            if (node.next != null) {
                System.out.print(", ");
            }
            node = node.next;
        }
        System.out.print("]\n");
    }

    /**
     * 清空链栈
     */
    public void clear() {
        while (stack != null) {
            LNode node = stack.next;
            stack.next = null;
            stack = null;
            stack = node;
        }
        stack = null;
    }
}

/**
 * 链栈结点
 */
class LNode {
    /**
     * 结点数据域
     */
    int data;
    /**
     * 结点指针域
     */
    LNode next;
}

测试代码:

public class LinkedStackTest {
    public static void main(String[] args) throws Exception {
        // 声明链栈
        LinkedStack stack = new LinkedStack();

        // 初始化链栈
        System.out.println("\n初始化链栈:");
        stack.init();
        stack.print();

        // 将元素入栈
        System.out.println("\n将元素入栈:");
        stack.push(11);
        stack.print();
        stack.push(22);
        stack.print();
        stack.push(33);
        stack.print();
        stack.push(44);
        stack.print();
        stack.push(55);
        stack.print();

        // 将元素出栈
        System.out.println("\n将元素出栈:");
        int ele;
        ele = stack.pop();
        stack.print();
        ele = stack.pop();
        stack.print();
        ele = stack.pop();
        stack.print();

        // 链栈是否为空
        System.out.println("\n链栈是否为空:");
        boolean empty;
        empty = stack.isEmpty();
        System.out.println(empty);

        // 获取栈顶结点数据
        System.out.println("\n获取栈顶结点数据:");
        int top;
        top = stack.getTop();
        System.out.println(top);

        // 获取链栈中元素个数
        System.out.println("\n获取链栈中元素个数:");
        int len;
        len = stack.size();
        System.out.println(len);

        // 清空链栈
        System.out.println("\n清空链栈:");
        stack.clear();
        stack.print();
    }
}

执行结果:

初始化链栈:
[]

将元素入栈:
[11]
[22, 11]
[33, 22, 11]
[44, 33, 22, 11]
[55, 44, 33, 22, 11]

将元素出栈:
[44, 33, 22, 11]
[33, 22, 11]
[22, 11]

链栈是否为空:
false

获取栈顶结点数据:
22

获取链栈中元素个数:
2

清空链栈:
[]
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值