算法与数据机构入门经典(算法题:包含min函数的栈)

   介绍下Leetcode简介:

   

  算法题: 包含min函数的栈

代码:

#include <stdio.h>
#include <malloc.h>
typedef struct ListNode ListNode;//struct ListNode = ListNode
struct ListNode { //定义结构体
    int data;
    ListNode *next;//链表的指针域  结构体指针:结构体变量的地址,指向某个结构体变量(同时也是结构体变量中第一个元素的地址) 
    //结构体指针变量中的值是所指向结构体变量的地址
    //我们可以通过结构体变量可以指向结构体中包含的一些成员
};
typedef struct Stack Stack;//struct Stack = Stack
struct Stack {
    ListNode *top_node; //栈顶元素的指针  if 没有 struct ListNode = ListNode,那么ListNode *top_node = ListNode ListNode *top_node
    int size; 
};

//进栈
void stack_push(Stack* stack, int val) {
    ListNode *new_node = (ListNode*)malloc(sizeof(ListNode));  //  1.新建节点。像操作系统申请一块内存,大小为ListNode,类型为ListNode *的空间给p指针变量,
                                                            /*sizeof(ListNode)计算ListNode所需要分配的空间大小
                                                            (ListNode*)malloc(...) 将返回的指针(void*)强制转换成ListNode**/
    new_node->data = val;  //  1,做相应赋值。结构体变量成员的访问 :结构体指针 ->成员名;如addr->country;
                          // (*结构体指针).成员名;(*addr).country;//很少去进行使用,注意必须去使用(),,因为*优先级大于.
                         // 结构体变量.成员名  stu.name
    new_node->next = stack->top_node; //2,将新节点的next指针指向当前的栈顶元素。将新添加的指针域(结构体指针)指向栈的栈顶元素的地址,
    stack->top_node = new_node;//3,将新节点设置为栈顶节点。使得新添加的节点变为栈顶元素
    stack->size += 1;//4.修改栈中元素个数。
}
 // 检验是否为空栈
int stack_is_empty(Stack *stack) {
    return (stack->top_node == NULL); //若stack->top_node == NULL 返回 1
}
//得到栈顶元素值返回
int stack_top(Stack *stack) {
    return stack->top_node->data; //stack->top_node->data 栈取栈顶元素值  相信为什么不能是stack.top_node.data
}
//删除栈顶元素
void stack_pop(Stack *stack) {
    //判断栈顶元素是否为空
    if (!stack->top_node) {
        return;
    }
    ListNode *top_node = stack->top_node; //备份栈顶指针指向的节点地址
    stack->top_node = stack->top_node->next;//修改栈顶指针,使其指向栈顶下方的元素
    stack->size -= 1;//修改栈中元素个数
    free(top_node);//释放原栈顶节点
}

//定义该栈:
typedef struct Minstack {
    Stack min;  //该栈存放的是当前栈栈最小元素
    Stack data;  //该栈存放的是当前栈顶元素
}Minstack;

//创造最小栈。相当于初始化在一个结构体下的两个结构体的值。
Minstack* minStackCreate(int maxSize) {
    Minstack * new_stack = (Minstack*)malloc(sizeof(Minstack));
    new_stack->min.top_node = NULL; // 结构体变量.成员名  使得结构体变量名为min的顶栈元素为NULL
    new_stack->min.size = 0; // 使得结构体变量为min的节点数为0
    new_stack->data.top_node = NULL; //结构体变量名为data的节点数为NULL
    new_stack->data.size = 0;//结构体变量名为data的节点数为0
    return new_stack;//返回 new_stack;
}

//进最小栈
void minStackPush(Minstack* obj,int x) {
    Stack *data = &(obj->data); //   结构体指针变量初始化: 结构体指针变量名 = &结构体变量;或者:结构体指针变量名 = &(结构体变量.第一个成员)
    Stack *min = &(obj->min);// 结构体指针必须要初始化以后才能够继续使用
    stack_push(data, x); //在data结构体变量名中进栈
    if (stack_is_empty(min)) { //判断min结构体变量名是否为空
        stack_push(min, x); //为空则进值x到min栈
    }
    else { //if 不为空,则进行下面操作
        if (x > stack_top(min)) { //if 加到data栈的x 比min栈的栈顶还大
            x = stack_top(min); // if为真,则把min栈的栈顶赋值给x 。
        }
        stack_push(min, x); //把x推进栈min(比min栈大则原来小的栈顶还是栈顶,x就留在data作为栈顶了,若比它小,则把min栈顶赋值给x进min栈)
    }
}

//删除栈栈顶
void minStackPop(Minstack* obj) {
    stack_pop(&(obj->data));//删除结构体指针变量 结构体变量的地址,指向某个结构体变量(同时也是结构体变量中第一个元素的地址)  所以把栈顶元素删除了
    stack_pop(&(obj->min)); //同上
}
//输出最小栈的栈顶
int minStackTop(Minstack* obj) {
    return stack_top(&(obj->data));
}
//输出最小栈的最小值
int minStackGetMin(Minstack* obj) {
    return stack_top(&(obj->min));
}
//释放最小栈
void minsStackFree(Minstack* obj) {
    free(obj);
}


int main() {
    Minstack *obj = minStackCreate(0);//创造一个结构体指针 将new_stack赋值给obj
    minStackPush(obj, -2);//进-2 到栈obj
    printf("top =[%d]\n", minStackTop(obj));
    printf("min =[%d]\n\n", minStackGetMin(obj));

    minStackPush(obj, 0);//进0 到栈obj
    printf("top =[%d]\n", minStackTop(obj));
    printf("min =[%d]\n\n", minStackGetMin(obj));

    minStackPush(obj, -5);//进-5 到栈obj
    printf("top =[%d]\n", minStackTop(obj));
    printf("min =[%d]\n\n", minStackGetMin(obj));

    minStackPop(obj);//删除栈min和栈data的栈顶
    printf("top =[%d]\n", minStackTop(obj));//输出data栈栈顶
    printf("min =[%d]\n\n", minStackGetMin(obj));//输出min栈最小栈
    minsStackFree(obj);
    return 0;
}

                                    

没有加注释,所以不是好代码。明儿有时间补上。(做到了!补上了!希望对你有帮助)

备注:有些知识需要补充下,关于结构体指针。


原因:

结果:


                                               

这张图可以加深理解。黑框里面分别是a的地址,a->next的地址,b的地址,b->next的地址。next指向下一个节点  就等于 next指向下一个节点  ,但是前一个节点的指针域存的就是下一个节点的地址、

知识点:

1.结构体指针的概念

概念:结构体变量的地址,指向某个结构体变量(同时也是结构体变量中第一个元素的地址) 
结构体指针变量中的值是所指向结构体变量的地址 
我们可以通过结构体变量可以指向结构体中包含的一些成员

定义一个结构体变量:

    struct 结构体名 *结构体指针变量名;
    如:struct address *addr;
  • 1
  • 2
  • 3

结构体指针变量初始化:

结构体指针变量名 = &结构体变量;
或者:结构体指针变量名 = &(结构体变量.第一个成员)
  • 1
  • 2
  • 3

注意:结构体指针必须要初始化以后才能够继续使用

2.结构体变量成员的访问

结构体指针 ->成员名;如addr->country;
(*结构体指针).成员名;(*addr).country;//很少去进行使用,注意必须去使用(),,因为*优先级大于.
结构体变量.成员名  stu.name
  • 1
  • 2
  • 3
  • 4

注意:如果是结构体指针的话,它是可以指向自己的(引用自己)

3.结构体指针的自引用

一个结构体内部包含一个指向该结构体本身的指针(必须是结构体指针) 
struct Self{ 
int a; 
int b; 
struct Self *s; //必须是结构体指针,指向自身 
}

关于结构体知识具体可以参考如下博客,十分详细:

https://blog.csdn.net/qq_29924041/article/details/54577724

感谢:来自四川成都的昌俊的悉心指导!

希望今日事情今日毕。

彩蛋:


猜你喜欢

转载自blog.csdn.net/qq_37791134/article/details/80869869