• 数据结构(1) 第一天 算法时间复杂度、线性表介绍、动态数组搭建(仿Vector)、单向链表搭建、企业链表思路


    01 数据结构基本概念_大O表示法

    无论n是多少都执行三个具体步骤

    执行了12步 O(12)=>O(1)

    O(n)

     

    log 2 N = log c N / log c N (相当于两个对数进行了一次运算)

    所以就不记入底数了,记作 O(logN)

    资料:

    (对数函数 a ≠ 1

    O(logN)

    O(n^2)

    n+(n-1)+(n-2)+ … 1 = n*(n+1)/2

    只关注最高次项n/2社区 n^2/2

    O(n^2)

    02 线性表基本概念

    03 动态数组框架搭建

     

    vector如何动态增长的:

    1 当插入一个新的元素的时候 发现空间不足?

    申请一块更大的内存空间

    2 将原空间的数据拷贝到新的空间

    3 释放旧的空间

    4 把元素放入新的空间

    1. 1.      先创建头文件 DynamicArray.h:

    里面定义好结构体 然后声明接口

    2.DynamicArray.c:

     

     

    04 动态数组框架实现

     

    05 动态数组测试

    dynamiclink.h:

    dynamiclink.c:

    source.c:

    06 单向链表框架搭建

    07 上午课程回顾

    1. 1.      算法的概念
    2. 2.      数据结构的概念

    时间复杂度:

    vector:

     

    链表插入

    newnode->next = pCurrent->next

    pCureent->next = newnode

    链表删除

    pCurrent->next = pNext->next

    free(pNext)

     

    linklist.h:

    #ifndef LINKLIST_H

    #define LINKLIST_H

     

     

    #include <stdlib.h>

    #include <stdio.h>

     

    // 链表节点

    typedef struct LINKNODE {

        void* data; // 指向任何类型的数据

        struct LINKNODE * next;

    }LinkNode;

     

     

    // 链表结构体

    typedef struct LINKLIST {

        // 头结点

        LinkNode * head;

        int size;

        // 需要容量吗? 没有容量的概念

    } LinkList;

     

     

    // 打印函数指针

    typedef void(*PRINTLINKNODE) (void *);

     

     

    // 初始化链表

    LinkList * Init_ListList();

    // 指定位置插入

    void Insert_LinkList(LinkList * list,int pos,void * data);

    // 删除指定位置的值

    void RemoveByPos_LinkList(LinkList* list, int pos);

    // 获得链表的长度

    void Size_LinkList(LinkList * list);

    // 查找

    int Find_LinkList(LinkList *list,void *data);

    // 打印链表节点

    void Print_LinkList(LinkList * list,PRINTLINKNODE print);

    // 返回第一个节点

    void * Front_LinkList(LinkList * list);

    // 释放链表内存

    void FreeSpace_Linklist(LinkList * list);

     

     

    #endif

     

    linklist.c:

    #include "Linklist.h"

     

    // 打印函数指针

    typedef void(*PRINTLINKNODE) (void *);

     

     

    // 初始化链表

    LinkList * Init_ListList()

    {

        // 进行初始化

                // 在堆空间上分配链表结构体大小 初始化size为0

        LinkList* list = (LinkList *)malloc(sizeof(LinkList));

        // 初始化size为0

        list->size = 0;

     

     

        // 头结点 是不保存数据的

        // 初始化一个结点 在堆空间上分配链表结点大小,将链表结构体的head指向该结点

        list->head = (LinkNode *)malloc(sizeof(LinkNode));

        // 初始化data为NULL

        list->head->data = NULL;

        // 初始化next为NULL

        list->head->next = NULL;

     

        // 返回链表结点

        return list;

    };

     

     

    // 指定位置插入

    void Insert_LinkList(LinkList * list, int pos, void * data)

    {

        if (list == NULL) {

            return;

        }

     

        if (data == NULL) {

            return;

        }

       

        // 友好的处理,pos越界

        if (pos<0 || pos >list->size) {

            // 如果越界了pos就是最大长度

            pos = list->size;

        }

     

        // 创建新的结点

        // 在堆空间分配链表结点

        LinkNode * newnode = (LinkNode*)malloc(sizeof(LinkNode));

        // 初始化data为data(注意:这里data的类型是void *

        newnode->data = data;

        // 初始化next为NULL

        newnode->next = NULL;

     

        // 找结点

        // 辅助指针变量

        // 辅助指针变量初始值为链表的第一个结点(即链表结构体head指向的结点

        LinkNode *pCurrent = list->head;

     

        // 假如传进来的pos是3 那么循环三次,找到pCurrent

        for (int i = 0; i < pos; i++)

        {

            pCurrent = pCurrent->next;

        }

     

       

        // 新结点入链表

        newnode->next = pCurrent->next;

        pCurrent->next = newnode;

     

        // 链表结构体的size++

        list->size++;

    };

     

    // 删除指定位置的值

    void RemoveByPos_LinkList(LinkList* list, int pos)

    {

        if (list == NULL) {

            return;

        }

     

        if (pos <0 || pos >= list->size) {

            return;

        }

     

        // 查找删除结点的前一个结点

        LinkNode *pCurrent = list->head;

     

        // 从第1个结点开始循环pos遍找到指定位置的链表结点

        // 比如我要删除第2个,就要找到第2个

        // 循环两边就指向了结点2

        for (int i = 0; i < pos-1;i++) {

            pCurrent = pCurrent->next;

        }

     

        // 缓存删除的结点

        LinkNode * PDel = pCurrent->next;

     

        pCurrent->next = PDel->next;

        // 释放删除结点的内存

        free(PDel);

     

        list->size--;

    };

     

     

    // 获得链表的长度

    void Size_LinkList(LinkList * list)

    {

        return list->size;

    };

     

    // 查找

    int Find_LinkList(LinkList *list, void *data)

    {

        if (list == NULL) {

            return -1;

        }

     

        if (data == NULL)

        {

            return -1;

        }

     

        // 遍历查找

        LinkNode * pCurrent = list->head->next;

     

        int i = 0;

     

        while (pCurrent != NULL) {

            if (pCurrent->data == data) {

                break;

            }

            i++;

            pCurrent = pCurrent->next;

        }

     

        return i;

    };

     

    // 打印链表节点

    void Print_LinkList(LinkList * list, PRINTLINKNODE print)

    {

        if (list == NULL) {

            return;

        }

     

        // 辅助指针变量

        LinkNode* pCurrent = list->head->next;

     

        while (pCurrent != NULL) {

            print(pCurrent->data);

            pCurrent = pCurrent->next;

        }

     

     

    };

     

     

    // 返回第一个节点

    void * Front_LinkList(LinkList * list){

        return list->head->next->data;

     

    };

     

     

    // 释放链表内存

    void FreeSpace_Linklist(LinkList * list) {

        if (list == NULL) {

            return;

        }

     

        // 辅助指针变量

        LinkNode *pCurrent = list->head;

        while (pCurrent != NULL) {

            // 缓存下一个结点

            LinkNode *pNext = pCurrent->next;

            free(pCurrent);

            pCurrent = pNext;

        }

     

     

        // 释放链表内存

        list->size = 0;

        free(list);

    };

     

     

    source.c:

     

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include "Linklist.h"

     

     

    // 自定义数据类型

    typedef struct PERSON {

        char name[64];

        int age;

        int score;

    } Person;

     

    // 打印函数

    void MyPrint(void * data) {

        Person * p = (Person *)data;

        printf("Name:%s Age:%d Score:%d ", p->name, p->age, p->score);

    }

     

    int main(void)

    {

        // 创建链表

        LinkList * list = Init_ListList();

     

        // 创建数据

        Person p1 = { "aaa",18,90 };

        Person p2 = { "bbb",19,50 };

        Person p3 = { "ccc",28,30 };

        Person p4 = { "ddd",17,100 };

        Person p5 = { "eee",16,23 };

     

     

        // 数据插入链表

        Insert_LinkList(list, 0, &p1);

        Insert_LinkList(list, 0, &p2);

        Insert_LinkList(list, 0, &p3);

        Insert_LinkList(list, 0, &p4);

        Insert_LinkList(list, 0, &p5);

       

        // 打印

        Print_LinkList(list, MyPrint);

     

     

        // 删除3

        RemoveByPos_LinkList(list, 3);

        printf(" ");

     

        Print_LinkList(list, MyPrint);

     

     

        // 返回第一个结点

        printf(" --------查找结果-------- ");

        Person * ret = (Person*)Front_LinkList(list);

        printf("Name:%s Age:%d Score:%d ", ret->name, ret->age, ret->score);

     

     

     

        // 销毁链表

        FreeSpace_Linklist(list);

     

        printf(" ");

        system("pause");

        return 0;

    }

    09 单向链表测试

     

    10 企业链表思路

     

    衣服上的挂钩:

     

    内核链表改进版 企业链表

    把挂钩放在最上面了:

     

    11 企业链表实现

     

    内核链表因为把指针放到最下面了 所以还要计算偏移  实现企业级链表  把指针小结点放到结构体最开始,使用强制转换来取到LinkListNode

    不用计算偏移

    linklist.c:

    #include "linklist.h"

     

    // 初始化链表

    LinkList * Init_LinkList()

    {

                        // 在堆内存上初始化LinkList结构体大小的

        LinkList *list = (LinkList*)malloc(sizeof(LinkList));

        // 初始化head的next为NULL

        list->head.next = NULL;

        // 初始化size为0

        list->size = 0;

        return list;

    }

     

     

    // 插入

    void Insert_LinkList(LinkList *list, int pos, LinkNode* data)

    {

        if (list == NULL) {

            return;

        }

     

        if (data == NULL) {

            return;

        }

     

        if (pos < 0 || pos > list->size) {

            pos = list->size;

        }

     

       

        // 查找插入位置

        // 辅助指针pCurrent是list的head的地址( 即那个小结点)

        // 用LinkNode *类型的指针pCurrent指向这个第0个链表的小结点

        LinkNode * pCurrent = &(list->head);

       

       

        for (int i = 0; i < pos; i++)

        {

            pCurrent = pCurrent->next;

        }

     

     

        // 假设pos是2 那么从0移动到 2

     

     

       

     

        // 插入新节点

        data->next = pCurrent->next;

        pCurrent->next = data;

     

        list->size++;

    }

     

     

    // 删除

    void Remove_LinkList(LinkList*list, int pos)

    {

     

        if (list == NULL) {

            return;

        }  

     

        if (pos<0 || pos >= list->size) {

            return;

        }

     

        // 辅助指针变量

        // LinkNode* 类型指针 指向第一个小结点

        LinkNode *pCurrent = &(list->head);

     

        for (int i = 0; i < pos; i++)

        {

            pCurrent = pCurrent->next;

        }

     

        // 删除结点

        pCurrent->next = pCurrent->next->next;

        list->size--;

    }

     

    // 查找

    // 传入回调函数 定义的回调函数指针是COMPARENODE

    int Find_LinkList(LinkList* list, LinkNode *data,COMPARENODE compare)

    {

        if (list == NULL) {

            return;

        }

     

        if (data == NULL)

        {

            return;

        }

     

        // 辅助指针变量

        LinkNode * pCurrent = list->head.next;

     

        int index = 0;

        int flag = -1;

     

        while (pCurrent != NULL) {

            if (compare(pCurrent, data) == 0) {

                flag = index;

                // 相等返回0

                break;

            }

            pCurrent = pCurrent->next;

            index++;

        }

     

        return flag;

    }

     

    // 返回链表大小

    int Size_LinkList(LinkList * list)

    {

        return list->size;

    }

     

    // 打印

    // 传入PRINTNODE类型回调函数

    void Print_LinkList(LinkList *list, PRINTNODE print)

    {

        if (list == NULL) {

            return;

        }

     

        // 辅助指针

        LinkNode * pCurrent = list->head.next;

       

        while (pCurrent != NULL)

        {

            print(pCurrent);

            pCurrent = pCurrent->next;

        }

    }

     

    // 释放链表内存

    void FreeSpace_LinkList(LinkList *list)

    {

        if (list == NULL) {

            return;

        }

     

        free(list);

    }

    linklist.h:

    #ifndef LINKLIST_H

    #define LINKLIST_H

     

    #include <stdlib.h>

    #include <stdio.h>

     

    // 链表小结点

    // 里面只有指针,指针指向小结点

    typedef struct LINKNODE {

        struct LINKNODE*next;

    } LinkNode;

     

     

    // 链表结点

    typedef struct LINKLIST {

        LinkNode head; // 链表小结点

        int size;      // size大小

    } LinkList;

     

     

     

     

    // 初始化链表

    LinkList * Init_LinkList();

     

    // 插入

    void Insert_LinkList(LinkList *list,int pos,LinkNode* data);

     

    // 删除

    void Remove_LinkList(LinkList*list,int pos);

     

    // 查找

    int Find_LinkList(LinkList* list,LinkNode *data,COMPARENODE compare);

     

    // 返回链表大小

    int Size_LinkList(LinkList * list);

     

    // 打印

    void Print_LinkList(LinkList *list,PRINTNODE print);

     

    // 释放链表内存

    void FreeSpace_LinkList(LinkList *list);

     

     

     

     

     

    // 遍历函数指针

    typedef void(*PRINTNODE) (LinkNode *);

     

    // 比较函数指针

    typedef int(*COMPARENODE) (LinkNode *, LinkNode *);

     

     

     

    #endif

    source.c:

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include "linklist.h"

     

    typedef struct PERSON {

        LinkNode node;

        char name[64];

        int age;

    } Person;

     

     

    void MyPrint(LinkNode * data) {

        Person* p = (Person *)data;

        printf("Name:%s Age:%d ", p->name, p->age);

    }

     

    int MyCompare(LinkNode * node1, LinkNode* node2) {

        Person *p1 = (Person *)node1;

        Person *p2 = (Person *)node2;

     

        if (strcmp(p1->name,p2->name) == 0 && p1->age == p2->age) {

            return 0;

        }

     

        return -1;

    }

     

    int main(void) {

     

        // 创建链表

        // 在堆上初始化LinkList结构体大小

        // Linklist的head指针 的next为NULL 初始化size值为0

        LinkList * list = Init_LinkList();

     

     

        // 创建数据

        // 在栈上创建对象

        Person p1, p2, p3, p4, p5;

        strcpy(p1.name, "aaa");

        strcpy(p2.name, "bbb");

        strcpy(p3.name, "ccc");

        strcpy(p4.name, "ddd");

        strcpy(p5.name, "eee");

     

        p1.age = 10;

        p2.age = 20;

        p3.age = 30;

        p4.age = 40;

        p5.age = 50;

     

        // 将结点插入到链表

        // list 在第0个位置插入data, 将p转成(LinkNode *)型的

        Insert_LinkList(list, 0, (LinkNode *)&p1);

        Insert_LinkList(list, 0, (LinkNode *)&p2);

        Insert_LinkList(list, 0, (LinkNode *)&p3);

        Insert_LinkList(list, 0, (LinkNode *)&p4);

        Insert_LinkList(list, 0, (LinkNode *)&p5);

     

     

        // 打印

        Print_LinkList(list, MyPrint);

     

        // 删除结点

        Remove_LinkList(list,2);

     

        // 打印

        printf("=============== ");

        Print_LinkList(list, MyPrint);

     

        // 查找

        Person findP;

        strcpy(findP.name, "bbb");

        findP.age = 20;

        int pos = Find_LinkList(list, (LinkNode*)&findP, MyCompare);

        printf("位置%d", pos);

     

     

        // 释放链表内存

        FreeSpace_LinkList(list);

     

        system("pause");

        return 0;

    }

  • 相关阅读:
    Emoji表情编解码库XXL-EMOJI
    代码生成平台Xxl-Code-Generator
    分布式单点登录框架XXL-SSO
    分布式爬虫框架XXL-CRAWLER
    Java对象和Excel转换工具XXL-EXCEL
    API管理平台XXL-API
    分布式缓存管理平台XXL-CACHE
    不知不觉已经写了多年代码,贴一下12年写的代码,表喷哈
    memcached安装、使用
    MySQL和Redis数据一致性问题
  • 原文地址:https://www.cnblogs.com/eret9616/p/10655058.html
Copyright © 2020-2023  润新知