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

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈练习之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

清空链栈:
[]

以上是关于栈练习之Example003-用不带头结点的单链表存储链栈并实现栈相关算法的主要内容,如果未能解决你的问题,请参考以下文章

线性表练习之Example042-设计一个递归算法,删除不带头结点的单链表 L 中所有值为 x 的结点

线性表练习之Example045-有一个带头结点的单链表 L,设计一个算法使其元素递增有序

线性表练习之Example032-将一个带头结点的单链表 A 分解成两个单链表 A 和 B,其中 A 表只包含原表中序号为奇数的元素,B 表中只包含原表中序号为偶数的元素

线性表练习之Example003-删除单链表最小值节点

线性表练习之Example020-将一个单链表拆分成两个链表,一个顺序一个倒序

经典算法学习——非循环双向链表实现冒泡排序(不带头结点)