数据结构(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. 先创建头文件 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\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)、单向链表搭建、企业链表思路的更多相关文章
- 【数据结构与算法】线性表操作(C++)
#include <stdio.h> #define maxSize 100 //定义整型常量maxSize值为100 /*顺序表的结构体定义*/ typedef struct SqLis ...
- Java数据结构与算法(1):线性表
线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列.形如如A0,A1,...,An-1.大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai. printList打印出表 ...
- c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)
线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...
- 线性表(存储结构数组)--Java 实现
/*线性表的数组实现 *特点:插入删除慢需要平均移动一半的数据,查找较快 *注意:有重复和无重复的数据对应的操作会有些不同 *注意数组一旦创建其大小就固定了 *Java集合长度可变是由于创建新的数组将 ...
- 【数据结构与算法】线性表操作(C语言)
#include <stdio.h> #include <stdlib.h> #define OK 1 #define NO 0 #define MAXSIZE 20 type ...
- "《算法导论》之‘线性表’":基于数组实现的单链表
对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 typedef int ElementType; cl ...
- 有序线性表(存储结构数组)--Java实现
/*有序数组:主要是为了提高查找的效率 *查找:无序数组--顺序查找,有序数组--折半查找 *其中插入比无序数组慢 * */ public class MyOrderedArray { private ...
- 线性表之顺序存储结构(C语言动态数组实现)
线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...
- 算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)
温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结.数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下.当然数据结构相关博客中我们以Swift语言来实现.因为Swift ...
随机推荐
- 一次完整的http事务
一次完整的http事务 https://www.processon.com/view/link/56c6679ce4b0f0c4285e69c0 规范把 HTTP 请求分为三个部分:状态行.请求头.消 ...
- HDU 4518
整理一下思路,明天再写... 这道题,其实就是求包含大于10的斐波那切数字的第K(K是斐波那契数)个数.注意到斐波那契数的爆炸性增长,所以在范围 内的符合要求的F数并不多吧.比如求第K个F数,那么,前 ...
- Using KafkaBolt to write to a kafka topic
https://community.hortonworks.com/questions/27187/using-kafkabolt-to-write-to-a-kafka-topic.html --- ...
- spring5.0新特性
spring5.0新特性 学习了:http://blog.csdn.net/u012562943/article/details/77449666 https://www.cnblogs.com/xu ...
- 【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)
上篇博文,我们简单的介绍了什么是SpringMVC.这篇博文.我们搭建一个简单SpringMVC的环境,使用非注解形式实现一个HelloWorld实例,从简单入手,逐步深入. 环境准备 我们须要有主要 ...
- HDU 2717
Catch That Cow Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- tomcat下载及启动
http://tomcat.apache.org/ 打开网页,在左边选择版本,选择后网页往下面拉 拉下来,根据windows选择32还是64位的,其中zip是windows免安装版 下载后解压,然后配 ...
- Android进程回收机制LMK(Low Memory Killer)【转】
本文转载自:http://www.cnblogs.com/wytiger/p/5744752.html 熟悉Android系统的童鞋都知道,系统出于体验和性能上的考虑,app在退到后台时系统并不会真正 ...
- 使用getopt命令解析shell脚本的命令行选项 【转】
本文转载自:http://yejinxin.github.io/parse-shell-options-with-getopt-command 在之前的一篇文章中,介绍了如何利用shell内置的get ...
- 0x63树的直径与最近公共祖先
凉 bzoj1999 先把树的直径求出来,从左往右枚举,对于当前位置i,找到满足限制并且最远的点j,当前位置最大值就是max(i~j区间内除直径外的子树路径长度最大值,1~i的长度,j~n的长度) 然 ...