线性表的逻辑结构
线性表是具有相同特性数据元素的有限序列 相同特性:把同一类事物归类,方便批量处理
有限:表中元素个数为n,n有限大,n可以为0
序列:表中元素排成一列,体现了一对的逻辑特性(每个元素有则仅有一个前驱和一个后继)
typedef struct
{
float height;
float weight;
}Human; //创建Human结构体
Human humans[10000];
for(int i=0;i<10000;++i)
{
处理1(humans[i].name);
处理2(humans[i].IDNumber);
处理3(humans[i].height);
}
[!note]+ AI 解释一下线性表中的相同特性,并用C语言体现并说明
线性表是一种数据结构,具有以下相同特性:
- 存储方式连续:线性表中的元素在内存中是连续存储的,每个元素占用相同大小的存储空间。
- 元素有序:线性表中的元素是按照一定的顺序排列的,每个元素都有一个确定的位置。
- 只有一个开始和结束位置:线性表只有一个起始位置和一个结束位置,每个元素只能通过前驱或后继关系找到其它元素。
C语言中可以通过数组来实现线性表。数组是一种连续存储的数据结构,可以根据下标随机访问其中的元素。下面是一个简单的示例代码:
#include <stdio.h>
#define MAXSIZE 100
typedef struct {
int data[MAXSIZE];
int length;
} List; //创建List 结构体,其中创建了一个一维数组的分量和length的分量
int main() {
List list;
list.length = 0;
// 插入元素
for (int i = 0; i < 10; i++) {
list.data[i] = i + 1;
list.length++;
}
// 遍历输出数组元素
for (int i = 0; i < list.length; i++) {
printf("%d ", list.data[i]);
}
return 0;
}
在上面的代码中,我们定义了一个结构体List
来表示线性表。其中data
数组用于存储元素,length
表示当前线性表中元素数量。在主函数中,我们首先创建了一个空列表,并通过循环向其中插入了10个整数。最后再通过循环遍历输出列表中所有元素。
这段代码体现了线性表连续、有序、只有一个开始和结束位置等特点。
线性表的存储结构
比较
顺序表:随机访问(随机存取) 占用连续的存储空间 链表:结点的存储空间利用率较顺序表稍低一点,支持存储空间的动态分配
顺序表更适合存取 链表更适合插入,删除
顺序存储结构
假设线性表的每个元素需占用l个存储单元, 并以所占的第一个单元的存储地址作为数据元 素的存储起始位置。则线性表中第i+ 1个数据元素的存储位置 LOC(a;+1 )和第i个数据元素的存 储位置LOC(a;)之间满足下列关系:
maxsize 地皮的个数
length是房子的个数
链式存储结构(单链表)
散落在内存的存储单元,线性表通过指针连列
判空条件L->next==NULL;
L表示头指针Head
typedef struct LNode
{
int data;
struct Lnode *next ;
}
头节点:不含数据元素的节点 开始节点:第一个含有数据元素的节点 与头节点(头指针)不同,头节点指向开始结点 结束节点:最后一个含有数据元素的节点,尾指针指向结束节点
通过C语言表现单链表节点和不相邻的节点的关系
在C语言中,可以通过结构体来表示单链表节点,如下所示:
struct ListNode {
int val;
struct ListNode *next;
};
其中,val表示节点的值,next表示下一个节点的指针。
若要表示不相邻的节点之间的关系,则可以使用数组来存储节点,并通过一个数组来记录它们之间的关系。例如:
#define MAX_NODES 100
struct GraphNode {
int val;
int neighbors[MAX_NODES];
};
struct GraphNode nodes[MAX_NODES];
其中,GraphNode表示图中的一个节点,val表示节点的值,neighbors是一个数组,存储该节点与其他所有节点之间的关系。
当需要连接两个不相邻的节点时,可以通过修改它们之间的neighbors数组来实现。例如:
void connect(struct GraphNode *node1, struct GraphNode *node2) {
node1->neighbors[node2->val] = 1;
node2->neighbors[node1->val] = 1;
}
其中,node1和node2分别是需要连接的两个节点。假设它们分别为i和j,则将node1->neighbors[j]和node2->neighbors[i]都设置为1即可实现它们之间的连接。
以上就是通过C语言表现单链表节点和不相邻的节点之间关系的方法。
链式存储结构(双链表)
每两个节点之间有两个链,两个指针前一个的后继,和后一个前驱 ![[双链表.excalidraw]]
typedef struct DLNode
{
int data;
struct DLNode *next;
struct DLNode *prior;
}DLNode;
DLNode *L'
L=(DLNode*)malloc(sizeof(DLNode));
A->next=B; B->next=C; C->next=D; //后继
D->prior=C; C->prior=b; B->prior=A; //前驱
判空条件:L->next == NULL && L->prior == NULL
L表示双链表的头节指针,L->next表示头节点的后继节点指针,L->prio表示头节点的前驱节点指针
L->next == NULL && L->prior == NULL
中的L是什么意思
L是一个指向双向链表的头节点的指针,表示该双向链表为空表。其中L->next表示头节点的后继节点指针,L->prior表示头节点的前驱节点指针。因为该双向链表为空表,所以这两个指针都应该为NULL。
如何判断双链表为空
判断双链表是否为空需要判断其头指针和尾指针是否都为NULL。因为双链表中的头指针和尾指针都是在初始化时赋值为NULL,若两者都为NULL,则说明该双链表为空。
代码示例:
typedef struct DNode {
int data;
struct DNode *prior; // 前驱节点指针
struct DNode *next; // 后继节点指针
} DNode, *DLinkList;
// 判断双链表是否为空
bool isEmpty(DLinkList L) {
if (L->next == NULL && L->prior == NULL) { // 头尾指针均为NULL
return true;
}
return false;
}
链式存储结构(循环链表)
单循环链表
当Head->next == Head
为真时,单循环链表为空
双循环链表
当Head->next==Head
且Head->prior==Head
时双循环链表为空
单循环链表和双循环链表不管什么情况下,都不会有空指针
不含头节点的单双循环链表
判空条件:Head==NULL
为真
当head指针为空时,两种链表为空,也就时不含头节点的单双循环链表一个节点都没有的时候,两种链表为空
malloc 申请链表节点空间
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <math.h>
#define min 0.0001
#define maxSize 100 //定义两个宏常量
using namespace std;
int compare(float A[], int An, float B[], int Bn) //An代表A表的长度,Bn代表B表的长度
{
int i = 0;
while (i < An && i < Bn) //表示i未遍历到AB表不同的地方
{
if (fabs(A[i] - B[i]) < min) //这里判断条件时AB表无线接近,可以视为相等
++i;
else
break;
}
if (i >= An && i >= Bn) //判断条件为AB是否相等
return 0;
else if ((i >=An && i < Bn) || A[i] < B[i])//a<b //
return -1;
else
return 1;
}
int main()
{
float A[maxSize] = { 1,2,3,4 };
float B[maxSize] = { 1,2,3,4,3,6 };
cout << compare(A, 4, B, 6);
return 0;
}