学习数据结构的第六天

文章介绍了单调栈数据结构,包括单调递增栈和单调递减栈的原理,以及如何使用单调栈算法解决给定整数数列中寻找元素右侧第一个大于或小于该元素的问题。通过C++代码展示了如何实现这个功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单调栈

单调栈是一种特殊的栈数据结构,它可以用来解决一类与单调性相关的问题。单调栈在处理一些需要维护元素单调性的场景中非常有用,例如寻找数组中每个元素右边第一个比它大(小)的数等问题   

单调栈分为单调递增栈和单调递减栈两种类型:

单调递增栈:当一个新元素要入栈时,如果它比栈顶元素大,则直接入栈 .(取大)

单调递减栈:当一个新元素要入栈时,如果它比栈顶元素小,则直接入栈.(取小)

题目描述

给出项数为 n 的整数数列 an​。

定义函数 f(i) 代表数列中第 i 个元素之后第一个大于 ai​ 的元素的下标,即 {}f(i)=mini<j≤n,aj​>ai​​{j}。若不存在,则 f(i)=0。

试求出 f(1…n)。

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

// 定义栈结构体
typedef struct {
    int* a;   // 数组指针
    int top;    // 栈顶指针
    int size;   // 栈大小
} Stack;

// 初始化栈
void initStack(Stack* stack, int size) {
    stack->a = (int*)malloc(size * sizeof(int));
    stack->top = -1;
    stack->size = size;
}

// 判断栈是否为空
int isEmpty(Stack* stack) {
    return stack->top == -1;
}

// 判断栈是否已满
int isFull(Stack* stack) {
    return stack->top == stack->size - 1;
}

// 入栈
void push(Stack* stack, int value) {
    if (isFull(stack)) {
        printf("Stack is full.\n");
        return;
    }
    stack->a[++(stack->top)] = value;
}

// 出栈
int pop(Stack* stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty.\n");
        return -1;
    }
    return stack->a[(stack->top)--];
}

// 获取栈顶元素
int peek(Stack* stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty.\n");
        return -1;
    }
    return stack->a[stack->top];
}

// 单调栈算法
void ddStack(int* a, int n, int* result) {
    Stack stack;
    initStack(&stack, n);

    for (int i = 0; i < n; i++) {
        while (!isEmpty(&stack) && a[peek(&stack)] < a[i]) {
            result[pop(&stack)] = i + 1;
        }
        push(&stack, i);
    }

    while (!isEmpty(&stack)) {
        result[pop(&stack)] = 0;
    }
}

int main() {
    int n;
    printf("请输入数列的项数:");
    scanf("%d", &n);

    int* a= (int*)malloc(n * sizeof(int));
    printf("请输入数列的元素:");
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }

    int* result = (int*)malloc(n * sizeof(int));
     ddStack(a, n, result);

    printf("f(1...%d) = ", n);
    for (int i = 0; i < n; i++) {
        printf("%d ", result[i]);
    }
    printf("\n");

    free(a);
    free(result);

    return 0;
}

在计算机科学和数据结构领域,树是一种重要的数据结构。它是一种非线性结构,由节点和边组成。树的概念类似于现实生活中的树,有根、分支和叶子。

  1. 树的基本概念 树由节点和边组成。每个节点都可以有零个或多个子节点,而除了根节点外,每个节点都有一个父节点。根节点是树的顶层节点,它没有父节点。叶子节点是没有子节点的节点。 

  • 树的存储结构的表示:a.双亲表示法        

#include <stdio.h>

#define MAX_SIZE 100

typedef struct TreeNode {
    int value;
    int parentIndex;
} TreeNode;

int main() {
    TreeNode tree[MAX_SIZE];  // 定义一个包含最大节点数的数组

    int n;  // 树的节点数量
     scanf("%d", &n);

    // 初始化树的所有节点
    for (int i = 0; i < n; i++) {
        printf("输入第%d个节点的值:", i + 1);
        scanf("%d", &(tree[i].value));
        tree[i].parentIndex = -1;  // 初始时将所有节点的父节点索引设为-1
    }

    // 输入每个节点的父节点索引
    for (int i = 1; i < n; i++) {
        int index, parentIndex;
        printf("输入节点%d的父节点索引:", i);
        scanf("%d", &parentIndex);

        if (parentIndex >= 0 && parentIndex < i) {  // 父节点索引合法性判断
            tree[i].parentIndex = parentIndex;
        } else {
            printf("父节点索引无效!\n");
            i--;  // 重新输入当前节点的父节点索引
        }
    }

    // 输出每个节点的值及其父节点的值
    printf("节点及其父节点信息:\n");
    for (int i = 0; i < n; i++) {
        printf("节点%d的值:%d,父节点的值:", i, tree[i].value);
        if (tree[i].parentIndex == -1) {
            printf("根节点\n");
        } else {
            printf("%d\n", tree[tree[i].parentIndex].value);
        }
    }

    return 0;
}
  •  b.孩子表示法 (暂时不会)

  •  c.孩子兄弟表示法

  1. 二叉树 二叉树是一种特殊的树结构,每个节点最多只能有两个子节点。一个子节点称为左子节点,另一个称为右子节点。二叉树的特点使得它在计算机科学中应用广泛,例如在搜索算法和排序算法中。  ( 目前还是粗略的了解)

  2. 树的遍历 树的遍历是指按照一定规则访问树中的所有节点。常用的遍历方法有三种:前序遍历、中序遍历和后序遍历。前序遍历先访问根节点,然后按照左子树、右子树的顺序遍历;中序遍历先访问左子树,然后访问根节点,最后访问右子树;后序遍历先访问左子树,然后访问右子树,最后访问根节点。

  3. 树的应用 树在计算机科学和软件工程中有广泛的应用。例如,在文件系统中,文件和文件夹可以组织成树形结构;在数据库中,索引结构通常使用树来提高查询效率;在人工智能中,决策树可以用于分类和预测等任务。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值