• 一些数据结构高(hao)逼(wu)格(liao)的实现方法


    这绝对是一篇很水很水的文章,你要相信。只是巩固自己对C指针的学习而已。


    学了辣么久的C语言。写了辣么多的数据结构。你是否还在用数组模拟你的链表、二叉树、字典树&&平衡树?
    今天无聊的我就来秀(shui)一(yi)秀(shui)我从大神那里学到的高逼格的实现方法把(对C语言指针有一定要求)。
    首先,定义数据结构的节点:
    链表是这样的:

    struct linkNode  {
    	typename data;
    	struct linkNode *next;
    }; //别忘了这里需要分号哦,详见C语言的结构体定义。
    

    喔这是最基本的实现。等下还可以有改进。
    然后是二叉树(平衡树适用)的:

    struct treeNode {
        typename data;
        struct treeNode *left, *right;
    };
    

    字典树:

    struct tireNode {
        typename data;
        struct treeNode *child[26];//好吧,这里极端点就改成255吧,也用不了多少空间。
    };
    

    其实都是一样的规则,只是每个节点连出去的指针的数量在变化。。好水!
    然后是新建节点的规则咯:
    首先定义全局变量(主要是为了申请空间,这是静态申请空间的方法,当然也可以申请动态内存):

    struct linkNode head[MAX_LEN], *pbuf = head;
    struct treeNode root[MAX_LEN], *pbuf = root;
    struct tireNode root[MAX_LEN], *pbuf = root;
    

    这里我就不考虑变量冲突的问题了,一般很少两种数据结构一起用的。
    链表的插入节点操作:

    void linkIns(typename x)
    {
        ++pbuf->data = x;
        Pbuf->next = head;
        head->next = pbuf;
    } //这里直接把节点插入到了链表头(你也可以自己改成插入到链表尾部)
    

    (我们默认定义链表头不存放数据,不然会有bug)。
    下面是二叉树的操作:
    (二叉树的版本太多了,所以这里给出的最水最水的创建节点吧,至于节点放哪里自己看情况而定把)

    struct treeNode* treeNodeNew(typename x)
    {
        ++pbuf->data = x;
        pbuf->left = pbuf->right = NULL;
        return pbuf;
    } //对你没看错就是这么简单。
    

    下面是字典树的操作(字典树是以插入一个字符串为操作的):

    void tireIns(char *s)
    {
    	struct  tireNode *p = root;
    	while(*s!='') {
    	    char ch = *s++ - 'a';//如果处理的字符串是大写的a换成A即可
    //如果大小写混合或者有特殊字符。可以用别的方法例如把child开成256的数组
    
    		if(p->child[ch] == NULL) 
            	p->child[ch] = ++pbuf;
    	    p = p->child[ch];
    	}
    	p->data ++; 
    	//这里的操作自定义啦啦啦 ,这里举的栗子素统计字符串数量的啦啦啦
    }
    

    当然数据结构肯定不止这些操作惹~其他的自己发挥把。。毕竟每一次使用都会有不同的情况。
    然后来看看这种静态的写法有什么缺点。。(缺点还是很明显的 +_+#)
    那就素!!删除节点的时候不释放内存空间!(因为是静态申请的嘛!)
    所以!!我就就需要在删除节点的时候(如果算法不需要删除就不需要这个啦)新建一个节点回收的指针数组!
    (!!注意是指针数组不是数组指针) 我称这个叫 垃圾回收机制!

    struct linkNode *recycleBin[MAX_LEN],  **rpbuf = recyckeBin; 
    void delete(struct linkNode * p) { ++rpbuf = p; }  //只需要在删除节
    

    点之前使用这个函数!就代表这个节点被删除了!
    另外两种就不写惹~一样的道理嘛!链表的理解了别的也就差不多了不是, 换汤不换药!
    当然,回收垃圾肯定是要有用的。。不然回收它干嘛。。所以我把link函数写成了这样:

    void linkIns(typename x)
    {
        struct linkNode * pNew;
        if(rpbuf != recycleBin) pNew = rpbuf;  //判断垃圾箱是否为空,不空从垃圾箱拿节点
        else pNew = pbuf;                      //如果空就从pbuf开新节点
        ++pNew->data = x;
        pNew->next = head->next;
        head->next = pNew;
    }
    

    二叉字典树树的就不水了。。。基本一样。。
    最后附上一个水水的栈!!

    typename stk[MAX_LEN],  *top = stk; //我在想用bottom素不素逼格更高一点@_@
    void push(typename x) { *++top = x; } //没错就素这么水!!
    typename *pop() { return top == stk ?  NULL :  top--} //没错一如既往的水!!
    

    话说栈就没必要写垃圾回收机制惹不是嘛~╰( ̄▽ ̄)╮
    然后再来水一水 动态节点的写法。。。
    主要用到一个函数malloc();函数原型详见C语言头文件 stdlib.h
    嗯 使用这个函数之前请先#include <stdlib.h>
    然后。。嗯 新建节点要申请内存。。例如:

    struct linkNode * linkNodeNew(typename x)
    {
            struct linkNode *plink = (struct linkNode *)malloc(sizeof(struct linkNode));
            plink->data = x;
            return plink;
    } 
    

    然后连接函数这样写:

    void link(struct linkNode *cur)
    {
            cur->next = head->next;
            head->next = cur;
    }  //当然还可以把两个函数合起来。。。
    

    其他的就不写了 换汤不换药的东西。。
    然后是删除节点。。这个就不需要垃圾回收了
    一个free函数直接还给操作系统。。

     void delete(struct linkNode * p) { free(p); } //真的好水。。。
    
  • 相关阅读:
    键盘ASCII码
    Pandas常用功能总结
    TensorFlow之多核GPU的并行运算
    Linux中目录以及路径问题
    菜鸟的服务器进阶
    ORA-02447: cannot defer a constraint that is not deferrable
    ORA-25153: Temporary Tablespace is Empty解决方法
    查询当前会话进程号
    Oracle中的USEREVN()
    Oracle物理结构与逻辑结构
  • 原文地址:https://www.cnblogs.com/SparkRat/p/4535610.html
Copyright © 2020-2023  润新知