数据结构

  1. 什么是数据结构

数据的逻辑结构以及存储结构及操作(数据的运算)

1.1 数据

数据:不再是单纯的数字,而是类似集合的概念

数据元素:是数据的基本单位,由若干个数据项组成

数据项:数据的最小单位,描述数据元素有用信息

数据元素又叫为节点

例如:

计算机处理的对象(数据)已不再是单纯的数值:

图书管理中的数据,如下表所列:

1 . 2 逻辑结构

数据元素并不是孤立存在的,它们之间存在着某种关系(或联系、结构)。元素和元素之间的关系:

  • 线性 关系

逻辑结构:线性结构

特点:一对一

线性结构:顺序表、链表、栈、队列

  • 层次 关系

逻辑结构:树形结构

特点:一对多

树形结构:二叉树

  • 网状 关系

逻辑结构:图状结构

特点:多对多

图状结构:图

例题:

田径比赛的时间安排问题

1 . 3 存储结构

数据的逻辑结构在计算机中的具体实现

1 . 3 . 1 顺序 存储

数组:连续存储

特点:内存连续、随机存取,每个元素占用空间较少

缺点:只能用一块大的且连续的空间,会产生一些碎片化的小空间

1 . 3 . 2 链式 存储

通过指针存储

特点:内存不连续,通过指针实现

链表实现:

结构体:

复制代码
#include <stdio.h>`

`struct` `node_t`
`{`
    `int data;`           `// 数据域:存放节点的数据`
    `struct` `node_t` `*next;// 指针域:结构体指针指向下一个节点`
`};`

`int` `main(int argc,` `char` `const` `*argv[])`
`{`
    `struct` `node_t A =` `{1,` `NULL};`
    `struct` `node_t B =` `{2,` `NULL};`
    `struct` `node_t C =` `{3,` `NULL};`

`    A.next =` `&B;`
`    B.next =` `&C;`
    `return` `0;`
`}`

`
1 . 4 . 3 索引 存储结构

在存储数据的同时,建立一个附加的索引表。

即索引存储结构=索引表+数据文件。

可以提高查找速度,特点检索速度快,但是占用内存多,删除数据文件要及时更改索引表。

例如:

这样查找一个电话就可以先查找索引表,再查找对应的数据文件,加快了查询的速度。但是如果删除或添加某个数据也要操作对应的索引表。

1 . 4 . 4 散列 存储

数据存储按照和关键码之间的关系进行存取。关系由自己决定,比如关键码是key, 存储位置也就是关系是key+1。获取关键数据,通过元素的关键码方法的返回值来获取。

存的时候按关系存

取的时候按关系取

1 . 5 操作

增 删 改 查

  1. 什么 算法

算法是解决问题的思想方法,数据结构是算法的基础。

2.1 算法的设计

算法的设计:取决于数据的逻辑结构

算法的实现:依赖于数据的存储结构

2 . 2 特性

有穷性:步骤是有限

确定性:每一个步骤有明确的含义,无二义性

可行性:规定的时间能完成

输入

输出

2 . 3 评价 算法 好坏

  1. 正确性
  2. 易读性
  3. 健壮性:容错处理
  4. 高效性:执行效率,通过重复执行的次数来判断,也就是可以通过时间复杂度

时间复杂度:

语句频度:用时间规模函数表达

时间规模函数:T(n) = O(f(n))

T(n) // 时间规模函数的时间函数

O // 时间数量级

n // 问题规模 例:a[100], n = 100

f(n) // 算法可执行语句重复执行次数

例子1:

求1+2+3+4+...+n的和

算法1:

int sum=0;

for(int i=1;i<=n;i++)

{

sum+=i;

}

// n = 100

f(n) = n;

T(n) = O(n);

算法2:

利用等差数列前n项和公式:Sn=n(a1+an)/2

int sum = n*(n+1)/2 // 当 n=100 重复执行一次

f(n) = 1;

O(f(n));

T(n) = O(1);

例2:

复制代码
int i, j;`
`for(i =` `0; i< n; i++)`
`{`
    `for(j =` `0; j< n; j++)`
    `{`
        `printf("ok\n");`
    `}`
`}`
`

// n*n 次

T(n) = O(n^2)

例3:

复制代码
int i, j;`
`for(i =` `0; i< n; i++)`
`{`
    `for(j =` `0; j<=i; j++)`
    `{`
        `printf("ok\n");`
    `}`
`}`

`

执行次数:1+2+3+..+n

f(n) = n*(n+1)/2;

= n^2/2+n/2; // 只保留最高项n^2/2,除以最高项系数 得到n^2

T(n) = O(n^2)

计算大O的方法

  1. 根据问题规模n写出表达式f(n)
  2. 如果有常数项,将其置为1 //当f(n)的表达式中只有常数项的时候,例如f(n)=8 ==> O(1)
  3. 只保留最高项,其他项舍去。
  4. 如果最高项系数不为1,则除以最高项系数。

f(n) = 3*n^4 + 2*n^3 + 6*n^7 +10;

==> O(n^7)

  1. 线性表

线性表是最基本、最简单、也是最常用的一种数据结构,可以存储逻辑关系为线性的数据。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

包含:顺序表(数组)、链表(单向链表、单向循环链表、双向链表、双向循环链表)、栈(顺序栈、链式栈)、队列(循环队列、链式队列)

逻辑结构:线性结构

存储结构:顺序存储(通过数组)或链式存储(通过指针)

特点:一对一,每个节点最多一个前驱和一个后继,首节点无前驱,尾节点无后继。

3 . 1 顺序表

顺序表存储数据的具体实现方案是:将数据全部存储到一整块内存空间中,数据元素之间按照次序挨个存放。

举个简单的例子,将 {1,2,3,4,5} 这些数据使用顺序表存储,数据最终的存储状态如下图所示:

3 . 1 . 1 顺序表 特性

特点:内存连续

逻辑结构:线性结构

存储结构:顺序存储

操作:增删改查

3 . 1 . 2 操作 数组

例题:

int a[100] = {1, 2, 3, 4, 5, 6, 7, 8};

函数命令规则:

下划线法:create_empty_seqlist

小驼峰法:createEmptySeqList

大驼峰法:CreateEmptySeqList

  1. 插入 数组 元素
复制代码
/*  `
`    功能:向数组的第几个位置插数据`
`    函数:void insetIntoA(int *p,int n, int post, int data);`
`    参数:`
`    int *p: 保存数组首地址`
`    int n: 有效数据元素的个数`
`    int post: 插入元素下标`
`    int data: 数据`
`*/`
`void` `insertIntoA(int` `*p,` `int n,` `int post,` `int data)`
`{`
    `// 1. 把从最后一个元素p[n-1]到插入位置元素 p[post]向后移动一个位置`
    `for(int i = n-1; i >= post; i--)`
`        p[i+1]` `= p[i];`
    `// 2. 插入新元素data到指定位置`
`    p[post]` `= data;`
`}`
`
  1. 遍历数组中 有效 元素
复制代码
/*`
`    功能:遍历数组中的有效元素`
`    函数:void showA(int *p,int n);`
`    参数:`
`    int *p:保存数组收地址`
`    int n:有效数据元素的个数`
`*/`
`void` `showA(int` `*p,int n)`
`{`
    `for(int i =` `0; i < n; i++)`
        `printf("%d ", p[i]);`
    `printf("\n");`
`}`
`
  1. 删除 数组元素
复制代码
/*  功能:删除数组中指定元素 `
`    函数:void deleteIntoA(int *p,int n, int post);`
`    参数:`
`    int *p: 保存数组首地址`
`    int n: 有效数据元素的个数`
`    int post: 删除元素下标`
`*/`
`void` `deleteIntoA(int` `*p,` `int n,` `int post)`
`{`
    `// 从删除位置后一个元素 p[post+1]到最后一个元素 p[n-1]往前移动一个单位`
    `for(int i = post+1; i < n; i++)`
`        p[i-1]` `= p[i];`
`}`

`
复制代码
#include <stdio.h>`

`void` `insertIntoA(int` `*p,` `int n,` `int post,` `int data)`
`{`
    `// 1. 把从最后一个元素p[n-1]到插入位置元素 p[post]向后移动一个位置`
    `for(int i = n-1; i >= post; i--)`
`        p[i+1]` `= p[i];`
    `// 2. 插入新元素data到指定位置`
`    p[post]` `= data;`
`}`
`void` `showA(int` `*p,int n)`
`{`
    `for(int i =` `0; i < n; i++)`
        `printf("%d ", p[i]);`
    `printf("\n");`
`}`
`void` `deleteIntoA(int` `*p,` `int n,` `int post)`
`{`
    `// 从删除位置后一个元素 p[post+1]到最后一个元素 p[n-1]往前移动一个单位`
    `for(int i = post+1; i < n; i++)`
`        p[i-1]` `= p[i];`
`}`
`int` `main(int argc,` `char` `const` `*argv[])`
`{`
    `int arr[100]` `=` `{1,` `2,` `3,` `4,` `5,` `6,` `7,` `8};`
    `insertIntoA(arr,` `8,` `2,` `100);`
    `showA(arr,` `9);`
    `deleteIntoA(arr,` `9,` `3);`
    `showA(arr,` `8);`
    `return` `0;`
`}`

`
  1. 添加 全局变量 l a s t 表示 有效 元素 下标
复制代码
#include <stdio.h>`

`int last =` `7;`  `// 代表最后一个有效元素的下标 last=有效元素个数-1`

`void` `insertIntoA(int` `*p,` `int post,` `int data)`
`{`
    `// 1. 把从最后一个元素p[n-1]到插入位置元素 p[post]向后移动一个位置`
    `for(int i = last; i >= post; i--)`
`        p[i+1]` `= p[i];`
    `// 2. 插入新元素data到指定位置`
`    p[post]` `= data;`

`    last++;`
`}`
`void` `showA(int` `*p)`
`{`
    `for(int i =` `0; i <= last; i++)`
        `printf("%d ", p[i]);`
    `printf("\n");`
`}`
`void` `deleteIntoA(int` `*p,` `int post)`
`{`
    `// 从删除位置后一个元素 p[post+1]到最后一个元素 p[n-1]往前移动一个单位`
    `for(int i = post+1; i <=last; i++)`
`        p[i-1]` `= p[i];`
`    last--;`
`}`

`int` `main(int argc,` `char` `const` `*argv[])`
`{`
    `int arr[100]` `=` `{1,` `2,` `3,` `4,` `5,` `6,` `7,` `8};`
    `insertIntoA(arr,` `2,` `100);`
    `showA(arr);`
    `deleteIntoA(arr,` `3);`
    `showA(arr);`
    `return` `0;`
`}`

`
3 . 1 . 3 顺序表 编程实现

seqlist.h

复制代码
#ifndef __SEQLIST_H__`
`#define __SEQLIST_H__`
`#define N 10`
`typedef` `struct` `seqlist`
`{`
    `int data[N];`
    `int last;` `//代表数组中最后一个有效元素的下标`
`}` `seqlist_t;`

`//1.创建一个空的顺序表`
`seqlist_t` `*CreateEpSeqlist();`
`//2.向顺序表的指定位置插入数据`
`int` `InsertIntoSeqlist(seqlist_t` `*p,` `int post,` `int data);`
`//3.遍历顺序表sequence顺序list表`
`void` `ShowSeqlist(seqlist_t` `*p);`
`//4.判断顺序表是否为满,满返回1,未满返回0`
`int` `IsFullSeqlist(seqlist_t` `*p);`
`//5.判断顺序表是否为空`
`int` `IsEpSeqlist(seqlist_t` `*p);`
`//6.删除顺序表中制定位置的数据`
`int` `DeleteIntoSeqlist(seqlist_t` `*p,` `int post);`
`//7.清空顺序表 (清空:访问不到,但是内存中还有;销毁:内存清空)`
`void` `ClearSeqList(seqlist_t` `*p);`
`//8.修改指定位置的数据,post为被修改数据位置,data为修改成的数据`
`int` `ChangePostSeqList(seqlist_t` `*p,int post,int data);`
`//9.查找制定数据出现位置,data为被查找的数据,返回下标,未找到返回-1`
`int` `SearchDataSeqList(seqlist_t` `*p,int data);`
`#endif`

`
相关推荐
禾风wyh44 分钟前
【PyTorch】回归问题代码实战
python·算法·机器学习
kikyo哎哟喂1 小时前
数据结构---图
数据结构
龙的爹23331 小时前
论文 | LazyLLM: DYNAMIC TOKEN PRUNING FOR EFFICIENTLONG CONTEXT LLM INFERENCE
人工智能·深度学习·算法·机器学习·自然语言处理·prompt·剪枝
我是哈哈hh2 小时前
专题二十四_贪心策略(2)_算法专题详细总结
数据结构·c++·算法·leetcode·贪心算法·贪心
程序猿小柒2 小时前
leetcode hot100【Leetcode 72.编辑距离】java实现
java·算法·leetcode
多吃轻食2 小时前
大模型开发和微调工具Llama-Factory-->训练方法(SFT, RLHF, DPO, KTO)
人工智能·深度学习·算法·自然语言处理·llama
Ws_2 小时前
leetcode LCP 开幕式焰火
开发语言·数据结构·python·算法·leetcode
纪怽ぅ2 小时前
深入傅里叶级数与傅里叶变换:从基础到应用
python·算法·机器学习·优化算法·傅里叶变化
tigerffff2 小时前
leetcode每日一题(20241203)
java·数据结构·算法·leetcode
L_cl2 小时前
【力扣热题100】—— Day3.反转链表
算法·leetcode·职场和发展