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. 先创建头文件 DynamicArray.h:
里面定义好结构体 然后声明接口
2.DynamicArray.c:
04 动态数组框架实现
05 动态数组测试
dynamiclink.h:
dynamiclink.c:
source.c:
06 单向链表框架搭建
07 上午课程回顾
- 1. 算法的概念
- 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;
}