菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
203
0

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

原创
05/13 14:22
阅读数 78112

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\n", 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("\n");

 

    Print_LinkList(list, MyPrint);

 

 

    // 返回第一个结点

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

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

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

 

 

 

    // 销毁链表

    FreeSpace_Linklist(list);

 

    printf("\n");

    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 \n", 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("===============\n");

    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;

}

 

发表评论

0/200
203 点赞
0 评论
收藏
为你推荐 换一批