simple又naive的数据结构

一、写在前面

  • 这一次包含的极其简单的数据结构有栈(载体为土豪送礼物的故事)、栈函数、队列(naive的循环队列)、链表(然而没有删除操作,还是一个待填的坑)。
  • 由此可见这些数据结构的功能还远没有完善,算法的效率也不高,这些都是大坑…需要参考前辈给出的答案再修改不过这都是填坑的后话了。

二、栈

题目要求就是一个栈一样的口袋收纳(输入0)和分发(输入1)礼物。收纳礼物,分发加人名。

#include <stdio.h>
#include <string.h>

int main(void){

    char present[50][10000];
    char name[50][10000];
    char presentf[50][10000];
    int num=0;
    int check=0;
    int xun=0;
    int precount=0;
    int namecount=0;

    scanf("%d",&num);

    for(xun=0;xun<num;xun++){
        scanf("%d",&check);
        if(check==1){
            scanf("%s",&present[precount]);
            precount++;
        }
        else if(check==2){
            scanf("%s",&name[namecount]);
            strcpy(presentf[namecount],present[precount-1]);
            namecount++;
            precount--;
        }
    }

    for(xun=0;xun<num/2;xun++){
        printf("%s\0",name[xun]);
        printf(" ");
        printf("%s\0",presentf[xun]);
        printf("\n");
    }

    return 0;
}
  • 形成数据结构栈,用来控制数据的额外的参数就是栈顶指针。他的操作包含栈顶指针的移动,还有判断栈为满还是空(这里最讨厌的就是要对应好边界不然很容易越界)。这个代码非常简单啊不懂要说啥了…

三、栈函数

#define STACK_MAX_SIZE 6

int stack_push(int *stack, int num);

int stack_pop(int *stack);

int stack_top(int *stack, int *ret);

int *stack_constructor(void);

void stack_destructor(int *stack);

#define STACK_MAX_SIZE_EX 7

int *stack_constructor(void){
    int * ptr;
    ptr=(int *)malloc(sizeof(int)*STACK_MAX_SIZE_EX);
    *ptr=1;
    return ptr;
}

void stack_destructor(int *stack){
    free(stack);
    return;
}

int stack_top(int *stack, int *ret){
    if(stack[0]==1)
    return 0;
    else{
        *ret=stack[stack[0]-1];
        return 1;
    }
}

int stack_push(int *stack, int num){
    if(stack[0]==7)
    return 0;
    else {
        stack[stack[0]]=num;
        stack[0]++;
        return 1;
    }
}

int stack_pop(int *stack){
    if(stack[0]==1)
    return 0;
    else {
        stack[0]--;
        return 1;
    }
}
  • 栈的操作:创建栈,压入,弹出,取栈顶值,清空内存。
  • 创建栈:如果创建多个栈的话,把栈顶指针整合到stack数组里面可以避免使用全局变量。而且可以非常方便的表示栈顶的数(stack[stack[0]])。
  • 清空内存:为了清空申请出的空间所以整个栈的头指针不能变化呢…所以才要用到栈顶指针吧。
  • 压入:首先要判断栈是否满了。压入数值之后要移动指针(即stack[0]1++),把栈顶指针一起整合到整个数组中真的非常方便呢。
  • 弹出:首先判断栈是否是空的。这里的思想大概是“伪装”删除数据的样子,下移指针之后顶上的数据就不会被读取,就如同被删除了一般。
  • 取栈顶:判断栈是否为空,然后就利用指针改值即可。
  • 如同一中所说,判断边界是很重要的,这份代码指针指向的是“空的可以放东西的栈顶”,所以判断栈的条件就是空1满7。如果指向的是已经放好东西的栈顶,就应该是空0满6,总之整份代码逻辑要相同。

四、队列

#include <stdio.h>

int main(void){
    int head=0, tail=0, distance=0, act=0, inp=0;
    int arry[10];

    while((act=getchar())!=EOF){
        if(act=='1'){
            scanf("%d",&inp);
            if(distance==10){
                printf("Push Failed. The queue is full.\n");
            }else{
                arry[head]=inp;
                head++;
                distance++;
                if(head==10)
                    head=0;}
        }else if(act=='0'){
            if(distance==0){
                printf("Pop Failed. The queue is empty.\n");
            }else{
                printf("%d\n",arry[tail]);
                tail++;
                distance--;
                if(tail==10)
                    tail=0; }
        }
    }

    return 0;
}
  • 让队列成为队列的额外的管理的参数是数据首尾的距离
  • 首尾距离:用来判断队列为满还是为空。
  • 头指针和尾指针:头指针用来表示下一个弹出的数,尾指针用来加入输入的数。区别于首尾距离的是他们是具体的数组的下标,对队列的满和空是不知情的。
    呃…头指针和尾指针需要在数组内循环,可以用if条件判断是否越界,然而简单的做法是指针%数组长。强…
  • 这里的指针移动也做到了“伪装删除”的效果。

五、链表

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h> 
typedef struct node {
    int value;
    struct node* next;
} node ;

int size=0; // the size of linked list
node* head; // the head of linkedlist


//insert the value to the right position
//if the position is not valid, return false
//if insert successfully, return true
bool insert(int position, int value);

// return the value in the given position
int get(int position);

//clear the linkedlist, remember to free the memory you allocated
void clear();

//#include "linkedList.h"

void print() {
    int i=0;
    for (i = 0; i < size; ++i) {
        printf("%d ", get(i));
    }
    printf("\n");
}


int main() {
    head = NULL;
    size = 0;
    int n, i, position, value;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d%d", &position, &value);
        if (insert(position, value)) {
            print();
        } else {
            printf("position is not valid\n");
        }
    }
    clear();
    return 0;
}

bool insert(int position, int value){
    int count=0;
    node *insert_node;
    node *former_node=head;
    if(position<0 || position>size){
        return false;
    }
    if(position==0){
        insert_node=(node *)malloc(sizeof(node));

        insert_node->next=head;
        insert_node->value=value;
        head=insert_node;
    size++;
        return true;
    }
    if(position==size){
        insert_node=(node *)malloc(sizeof(node));

        insert_node->value=value;
        insert_node->next=NULL;

        for(count=0;count<position-1;count++){
            former_node=former_node->next;
        }
        former_node->next=insert_node;
    size++;
        return true;
    }else{
        for(count=0;count<position-1;count++){
            former_node=former_node->next;
        }
        insert_node=(node *)malloc(sizeof(node)); 

        insert_node->value=value;
        insert_node->next=former_node->next; 

        former_node->next=insert_node;
            size++;
        return true;
    }
}

int get(int position){
    int count=0;
    node *num=head;
    if(position==0){
        return head->value;
    }

    for(count=0;count<position;count++){
        num=num->next;
    }

    return num->value;
}

void clear(){
    int count=0;
    node *go=head;
    node *save;
    for(count=0;count<size;count++){
        save=go->next;
        free(go);
        go=save;
    }
    return;
}
  • 一个要填的坑:没有删除数据的函数
  • 链表由结构完成:数据域+结构域。数据域就是正常的填入和输出数据就好了。而结构域就是形式上串联起整个链表的指针:指向下一个结构。
  • 读取函数:比数组麻烦而且整个链表在->next的过程中一定要想好循环多少次…边界问题…数据结构的家常便饭啊。这里要判断是否读第一个数据的问题。
  • 清空函数:想不出别的方法只能用两个变量循环存储再删除了…不然总会丢失下一个地址free就会失败。
  • 插入数据的函数:重头戏。先要判断是否插入的是头,尾。
    插入头:把head存到自己的指向下一个的指针中,更改head指针为自己。
    插入尾:更改原尾指针,并且把自己的下一个指针指向NULL。
    插入中间:整个过程为:开辟新内存→存入值,把指针指向原本的下一个值→再把前一个指针指向自己。如果后两步做反了的话就会丢失下一个值的地址然后断链。插入头的时候指针的更改也是需要遵循这样的逻辑:先拿到下一个,在连接上一个。
  • size参数:记录链表长度的全局参数(不然…?)。插入的时候的重要依据,在插入函数里面要对其进行增减。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值