数据结构(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 ...
随机推荐
- cogs 10. 信号无错传输
10. 信号无错传输 ★★☆ 输入文件:dlj.in 输出文件:dlj.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 为提高传递信息的保密性和可靠性,两个军事 ...
- SQL优化(SQL TUNING)之10分钟完毕亿级数据量性能优化(SQL调优)
前几天.一个用户研发QQ找我,例如以下: 自由的海豚. 16:12:01 岛主,我的一条SQL查不出来结果,能帮我看看不? 兰花岛主 16:12:10 多久不出结果? 自由的海豚 16:12:17 多 ...
- Linux学习笔记:什么是x86
什么是x86 和硬件打交道常常会听说x86,疑惑的时候自己翻过书上网查过资料.可是都不甚明白.近期再次遇到x86这个词,随具体了解并做笔记记录. 想要知道什么是x86应该先区分CPU的分类. CPU ...
- GMGDC专訪戴亦斌:具体解释QAMAster全面測试服务6大功能
GMGDC专訪戴亦斌:具体解释QAMAster全面測试服务6大功能 2014/10/10 · Testin · 业界资讯 在9月24-25日第三届全球移动游戏开发人员大会上,Testin云測COO戴亦 ...
- iOS 块的简单理解
占位 自己主动转载器那小子,你转完了没? 转完了,我开写了哈! Block,就两个事儿,一个是引用,一个是实例,除了实现处.其他地方都是引用. 以此思路.再继续看看引用和实现的定义方式吧. 參考官方文 ...
- Linux命令(七)——网络配置和网络通信
在使用网络前,需要对linux主机进行基本的网络配置,配置后可以使该主机能够同其他主机进行正常的通信. 一.网络配置 1.ifcfg-ethn网络配置文件 所有的网络接口配置文件均存放在/etc/sy ...
- 约瑟夫环问题的链表解法和数学解法(PHP)
约瑟夫环问题 一群猴子排成一圈.按1,2,-,n依次编号.然后从第1仅仅開始数,数到第m仅仅,把它踢出圈.从它后面再開始数,再数到第m仅仅.在把它踢出去-.如此不停的进行下去.直到最后仅仅剩下一仅仅猴 ...
- Cookies操作类
实现代码: //声名一个数据集合 var listString = new List<string>() { "a", "b", "c&q ...
- J2EE7与Servlet3.x
J2EE7结构图 JWS:即Java Web Service,指与webservice相关的JavaEE技术部分,webservice是一种基于XML的独立的.跨平台的.互操作的应用程序,XML又包含 ...
- JS函数种类详解
1. 普通函数1.1 示例 1 2 3 function ShowName(name) { alert(name); } 1.2 Js中同名函数的覆盖 在Js中函数是没有重载,定义相同函数名.不同 ...