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;

}

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

  1. 【数据结构与算法】线性表操作(C++)

    #include <stdio.h> #define maxSize 100 //定义整型常量maxSize值为100 /*顺序表的结构体定义*/ typedef struct SqLis ...

  2. Java数据结构与算法(1):线性表

    线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列.形如如A0,A1,...,An-1.大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai. printList打印出表 ...

  3. c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)

    线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...

  4. 线性表(存储结构数组)--Java 实现

    /*线性表的数组实现 *特点:插入删除慢需要平均移动一半的数据,查找较快 *注意:有重复和无重复的数据对应的操作会有些不同 *注意数组一旦创建其大小就固定了 *Java集合长度可变是由于创建新的数组将 ...

  5. 【数据结构与算法】线性表操作(C语言)

    #include <stdio.h> #include <stdlib.h> #define OK 1 #define NO 0 #define MAXSIZE 20 type ...

  6. "《算法导论》之‘线性表’":基于数组实现的单链表

    对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 typedef int ElementType; cl ...

  7. 有序线性表(存储结构数组)--Java实现

    /*有序数组:主要是为了提高查找的效率 *查找:无序数组--顺序查找,有序数组--折半查找 *其中插入比无序数组慢 * */ public class MyOrderedArray { private ...

  8. 线性表之顺序存储结构(C语言动态数组实现)

    线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...

  9. 算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)

    温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结.数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下.当然数据结构相关博客中我们以Swift语言来实现.因为Swift ...

随机推荐

  1. Spring Cloud Stream(十三)

    说明 对Spring Boot 和 Spring Integration的整合,通过Spring Cloud Stream能够简化消息中间件使用的复杂难度!让业务人员更多的精力能够花在业务层面 简单例 ...

  2. mybatis使用-helloword(一)

    前言 首先感谢https://my.oschina.net/zudajun/blog/665956(jd上也出书了貌似)  这位作者.让自己能系统的看完和理解第一个框架的源码(其实我反复看了4遍以上, ...

  3. [bzoj1861][Zjoi2006]Book 书架_非旋转Treap

    Book 书架 bzoj-1861 Zjoi-2006 题目大意:给你一个序列,支持:将指定编号的元素抽出,放到序列顶(底):将指定编号元素左右篡位:查询指定编号元素位置:查询指定数量位置元素编号. ...

  4. UVA - 348Optimal Array Multiplication Sequence(递推)

    id=19208">题目:Optimal Array Multiplication Sequence 题目大意:给出N个矩阵相乘.求这些矩阵相乘乘法次数最少的顺序. 解题思路:矩阵相乘 ...

  5. 零基础学python-2.16 列表解析

    这一节聊聊强大的列表解析 主要就是在一行里面赋值给列表 以下我们举两个样例: 上面的样例我们引入了range函数,他主要作用是在一定范围里面取整数值 我来解释一下中括号中面的那一句:x**2 for ...

  6. 18005 It is not ugly number

    18005 It is not ugly number 时间限制:2000MS  内存限制:65535K提交次数:0 通过次数:0 题型: 编程题   语言: G++;GCC Description ...

  7. sizeof运算符、malloc函数及free函数

    一.sizeof运算符的用法 1.sizeof运算符给出某个类型或变量在内存中所占据的字节数. int a;  sizeof(a)=4;  //sizeof(int)=4; double b;  si ...

  8. ssh 结构

    service:业务层 dao:数据訪问层 hibernate:持久层

  9. oc20--继承2

    // // Phone.h #import <Foundation/Foundation.h> // 被继承的这个类我们称之为父类/ 超类 @interface Phone : NSObj ...

  10. kali 下使用 arpspoof 实现 ARP 欺骗

    ARP 欺骗: 一种中间人攻击,攻击者通过毒化受害者的 ARP 缓存,将网关的 MAC 替换成攻击者的 MAC ,于是攻击者的主机实际上就充当了受害主机的网关, 之后攻击者就可以截获受害者发出和接到的 ...