大连市那里做网站宣传的好,传奇游戏排行榜,什么是企业,网站在哪里变更备案信息文章目录 【 1. 基本原理 】1.1 静态链表中的节点1.2 备用链表 【 2. 静态链表的创建 】2.1 实例1 - 创建静态链表#xff0c;指定值2.2 实例2 - 创建静态链表#xff0c;默认值 【 3. 静态链表 添加元素 】【 4. 静态链表 删除元素 】【 5. 静态链表 查找元素 】【 6. 静态链… 文章目录 【 1. 基本原理 】1.1 静态链表中的节点1.2 备用链表 【 2. 静态链表的创建 】2.1 实例1 - 创建静态链表指定值2.2 实例2 - 创建静态链表默认值 【 3. 静态链表 添加元素 】【 4. 静态链表 删除元素 】【 5. 静态链表 查找元素 】【 6. 静态链表 更改数据 】【 7. 实例 - 静态链表的增删查改 】 【 1. 基本原理 】
静态链表也是线性存储结构的一种它兼顾了顺序表和链表的优点于一身可以看做是顺序表和链表的升级版。使用静态链表存储数据 数据全部存储在数组中和顺序表一样但存储位置是随机的数据之间的逻辑关系通过一个整形变量称为游标和指针功能类似维持和链表类似。通过 “数组游标” 的方式存储具有线性关系数据的存储结构就是 静态链表。 通常静态链表会将 第一个数据元素放到数组下标为 1 的位置a[1]中。 例如使用静态链表存储 {1,2,3} 的过程如下 创建一个足够大的数组假设大小为 6如图所示 在将数据存放到数组中时给各个数据元素配备一个整形变量此变量用于指明各个元素的直接后继元素所在数组中的位置下标如图所示 从 a[1] 存储的数据元素 1 开始通过存储的游标变量 3就可以在 a[3] 中找到元素 1 的直接后继元素 2同样通过元素 a[3] 存储的游标变量 5可以在 a[5] 中找到元素 2 的直接后继元素 3这样的循环过程直到某元素的游标变量为 0 截止因为 a[0] 默认不存储数据元素。 1.1 静态链表中的节点
静态链表存储数据元素也需要自定义数据类型至少需要包含以下 2 部分信息 数据域用于存储数据元素的值游标其实就是数组下标表示直接后继元素所在数组中的位置 因此静态链表中节点的构成用 C 语言实现为
typedef struct
{int data;//数据域int cur;//游标
}component;1.2 备用链表
上图显示的静态链表还不够完整静态链表中除了数据本身通过游标组成的链表外还需要有一条连接各个空闲位置的链表称为 备用链表。备用链表的作用是 回收数组中未使用或之前使用过目前未使用的存储空间留待后期使用。 静态链表中设置备用链表的好处是可以清楚地知道数组中是否有空闲位置以便数据链表添加新数据时使用。所以说静态链表使用数组申请的物理空间中存有两个链表 数据链表 用于 连接数据。表头通常位于数组下标为 1 的位置即 表头a[1] 。备用链表 用于 连接数组中未使用的空间 。表头通常位于数组下标为 0 的位置即 表头a[0] 。 备用链表最后1个节点的游标为 0 即指向表头备用链表第1个节点存有值则表明数据已存满 。 例如使用静态链表存储 {1,2,3}假设使用长度为 6 的数组 a则存储状态可能如下图 所示 下图中备用链表上连接的依次是 a[0]、a[2] 和 a[4]而数据链表上连接的依次是 a[1]、a[3] 和 a[5]。 【 2. 静态链表的创建 】
假设使用静态链表数组长度为 6存储 1,2,3 则需经历以下几个阶段 在数据链表未初始化之前数组中所有位置都处于空闲状态因此都应被链接在备用链表上如下图所示 当向静态链表中添加数据时需提前从备用链表中摘除节点以供新数据使用。 备用链表 摘除节点最简单的方法是摘除 a[0] 的直接后继节点同样向备用链表中 添加空闲节点也是添加作为 a[0] 新的直接后继节点。因为 a[0] 是备用链表的第一个节点我们知道它的位置操作它的直接后继节点相对容易无需遍历备用链表耗费的时间复杂度为 O(1)。 向静态链表中添加元素 1 的过程如下图所示 在上图的基础上添加元素 2 的过程如下图所示 在上图的基础上继续添加元素 3 过程如下图所示。由此静态链表就创建完成了。 2.1 实例1 - 创建静态链表指定值
#include stdio.h
#define maxSize 6// 静态链表结构体
typedef struct
{int data; // 数据int cur; // 游标指向下一个存有数据的节点
}component;// 创建备用链表
// 将结构体数组中所有结构体即节点链接起来节点的数据默认设置为-1
void reserveArr(component* array)
{for (int i 0; i maxSize; i){array[i].cur i 1;//将每个结构体数组中每个结构体链接到一起array[i].data -1;}array[maxSize - 1].cur 0;//备用链表的最后一个结点的游标值为0
}// 提取分配空间从备用链表上摘下一个空闲节点返回该空闲结点的下标
// 若备用链表非空则将表头的游标指向下下一个空闲的节点;
// 若表链空则返回0即将表头这个空闲节点用于分配。
int mallocArr(component* array)
{int i array[0].cur;if (array[0].cur) //若备用链表非空即表头的游标≠0则表头的游标指向下下一个空闲的节点array[0].cur array[i].cur;return i;
}// 从备用链表中申请内存为数据链表赋初值
void initArr(component* array,int y[],int n)
{reserveArr(array);int tempBody array[0].cur;int j;for (int i 0; i n; i) {j mallocArr(array); //从备用链表中拿出空闲的分量,j1,2,3,4array[j].data y[i]; //给新申请的分量的数据域初始array[tempBody].cur j; //将申请的空闲分量链接在链表的最后一个结点后面tempBody j;//将指向链表最后一个结点的指针后移}array[tempBody].cur 0; //将申请的空闲分量链接在链表的最后一个结点后面
}//输出函数
void displayArr(component* array)
{for(int j0;jmaxSize;j)printf(a[%d],\tdata%d\t,cur%d\n,j, array[j].data, array[j].cur);
}int main()
{int x[4] { 3,1,4,5 };component array[maxSize];initArr(array, x,4);printf(静态链表为\n);displayArr(array);return 0;
}2.2 实例2 - 创建静态链表默认值
#include stdio.h
#define maxSize 6// 静态链表结构体
typedef struct
{int data; // 数据int cur; // 游标指向下一个存有数据的节点
}component;// 创建备用链表
// 将结构体数组中所有结构体即节点链接起来节点的数据默认设置为-1
void reserveArr(component* array)
{for (int i 0; i maxSize; i){array[i].cur i 1;//将每个结构体数组中每个结构体链接到一起array[i].data -1;}array[maxSize - 1].cur 0;//备用链表的最后一个结点的游标值为0
}// 提取分配空间从备用链表上摘下一个空闲节点返回该空闲结点的下标
// 若备用链表非空则将表头的游标指向下下一个空闲的节点;
// 若表链空则返回0即将表头这个空闲节点用于分配。
int mallocArr(component* array)
{int i array[0].cur;if (array[0].cur) //若备用链表非空即表头的游标≠0则表头的游标指向下下一个空闲的节点array[0].cur array[i].cur;return i;
}// 从备用链表中申请内存为数据链表赋初值
void initArr(component* array)
{reserveArr(array);int tempBody array[0].cur;int j;for (int i 1; i 4; i) {j mallocArr(array); //从备用链表中拿出空闲的分量,j1,2,3,4array[j].data i; //给新申请的分量的数据域初始array[tempBody].cur j; //将申请的空闲分量链接在链表的最后一个结点后面tempBody j;//将指向链表最后一个结点的指针后移}array[tempBody].cur 0; //将申请的空闲分量链接在链表的最后一个结点后面
}//输出函数
void displayArr(component* array)
{for(int j0;jmaxSize;j)printf(a[%d],\tdata%d\t,cur%d\n,j, array[j].data, array[j].cur);
}int main()
{component array[maxSize];initArr(array);printf(静态链表为\n);displayArr(array);return 0;
}【 3. 静态链表 添加元素 】
在上图的基础将元素 4 添加到静态链表中的第 3 个位置上实现过程如下 从备用链表中摘除一个节点用于存储元素 4找到表中第 2 个节点添加位置的前一个节点这里是数据元素 2将元素 2 的游标赋值给新元素 4将元素 4 所在数组中的下标赋值给元素 2 的游标 C 语言实现以上操作
//向链表中插入数据body表示链表的头结点在数组中的位置add表示插入元素的位置a表示要插入的数据
void insertArr(component * array,int body,int add,char a)
{int tempBodybody;//tempBody做遍历结构体数组使用//找到要插入位置的上一个结点在数组中的位置for (int i1; iadd; i) tempBodyarray[tempBody].cur;int insertmallocArr(array);//申请空间准备插入array[insert].dataa;array[insert].curarray[tempBody].cur;//新插入结点的游标等于其直接前驱结点的游标array[tempBody].curinsert;//直接前驱结点的游标等于新插入结点所在数组中的下标
}【 4. 静态链表 删除元素 】
静态链表中删除指定元素只需实现以下 2 步操作 将存有目标元素的节点从数据链表中摘除将摘除节点添加到备用链表以便下次再用 若问题中涉及大量删除元素的操作建议在建立静态链表之初创建一个带有头节点的静态链表方便实现删除链表中第一个数据元素的操作。C 语言代码为
//备用链表回收空间的函数其中array为存储数据的数组k表示未使用节点所在数组的下标
void freeArr(component * array,int k)
{array[k].curarray[0].cur;array[0].curk;
}
//删除结点函数a 表示被删除结点中数据域存放的数据
void deletArr(component * array,int body,char a)
{int tempBodybody;//找到被删除结点的位置while (array[tempBody].data!a) {tempBodyarray[tempBody].cur;//当tempBody为0时表示链表遍历结束说明链表中没有存储该数据的结点if (tempBody0) {printf(链表中没有此数据);return;}}//运行到此证明有该结点int deltempBody;tempBodybody;//找到该结点的上一个结点做删除操作while (array[tempBody].cur!del) {tempBodyarray[tempBody].cur;}//将被删除结点的游标直接给被删除结点的上一个结点array[tempBody].curarray[del].cur;//回收被摘除节点的空间freeArr(array, del);
}【 5. 静态链表 查找元素 】
静态链表查找指定元素由于我们只知道静态链表第一个元素所在数组中的位置因此只能通过逐个遍历静态链表的方式查找存有指定数据元素的节点。C 语言实现代码如下
//在以body作为头结点的链表中查找数据域为elem的结点在数组中的位置
int selectElem(component * array,int body,char elem)
{int tempBodybody;//当游标值为0时表示链表结束while (array[tempBody].cur!0) {if (array[tempBody].dataelem) return tempBody;tempBodyarray[tempBody].cur;}return -1;//返回-1表示在链表中没有找到该元素
}【 6. 静态链表 更改数据 】
更改静态链表中的数据只需找到目标元素所在的节点直接更改节点中的数据域即可。C 语言代码如下
//在以body作为头结点的链表中将数据域为oldElem的结点数据域改为newElem
void amendElem(component * array,int body,char oldElem,char newElem)
{int addselectElem(array, body, oldElem);if (add-1){printf(无更改元素);return;}array[add].datanewElem;
}【 7. 实例 - 静态链表的增删查改 】
#include stdio.h
#define maxSize 7//静态链表结构体
typedef struct
{char data;int cur;
}component;//创建备用链表
//将结构体数组中所有分量链接到备用链表中
void reserveArr(component* array)
{for (int i 0; i maxSize; i) {array[i].cur i 1;//将每个数组分量链接到一起array[i].data ; // 默认赋值为空格}array[maxSize - 1].cur 0;//链表最后一个结点的游标值为0
}//从备用链表中摘除空闲节点的实现函数
//提取分配空间
int mallocArr(component* array)
{//若备用链表非空则返回分配的结点下标否则返回0当分配最后一个结点时该结点的游标值为0int i array[0].cur;if (array[0].cur)array[0].cur array[i].cur;return i;
}//将摘除下来的节点链接到备用链表上
void freeArr(component* array, int k)
{array[k].cur array[0].cur;array[0].cur k;
}//初始化静态链表
int initArr(component* array)
{reserveArr(array);int body mallocArr(array);//声明一个变量把它当指针使指向链表的最后的一个结点因为链表为空所以和头结点重合int tempBody body;for (int i 1; i 5; i) {int j mallocArr(array);//从备用链表中拿出空闲的分量array[tempBody].cur j;//将申请的空线分量链接在链表的最后一个结点后面array[j].data a i - 1;//给新申请的分量的数据域初始化tempBody j;//将指向链表最后一个结点的指针后移}array[tempBody].cur 0;//新的链表最后一个结点的指针设置为0return body;
}//向链表中插入数据body表示链表的头结点在数组中的位置add表示插入元素的位置a表示要插入的数据
void insertArr(component* array, int body, int add, char a)
{int tempBody body;for (int i 1; i add; i)tempBody array[tempBody].cur;int insert mallocArr(array);array[insert].cur array[tempBody].cur;array[insert].data a;array[tempBody].cur insert;
}//删除链表中含有字符a的结点
void deletArr(component* array, int body, char a)
{int tempBody body;//找到被删除结点的位置while (array[tempBody].data ! a){tempBody array[tempBody].cur;//当tempBody为0时表示链表遍历结束说明链表中没有存储该数据的结点if (tempBody 0){printf(链表中没有此数据);return;}}//运行到此证明有该结点int del tempBody;tempBody body;//找到该结点的上一个结点做删除操作while (array[tempBody].cur ! del){tempBody array[tempBody].cur;}//将被删除结点的游标直接给被删除结点的上一个结点array[tempBody].cur array[del].cur;freeArr(array, del);
}//查找存储有字符elem的结点在数组的位置
int selectElem(component* array, int body, char elem)
{int tempBody body;//当游标值为0时表示链表结束while (array[tempBody].cur ! 0){if (array[tempBody].data elem)return tempBody;tempBody array[tempBody].cur;}return -1;//返回-1表示在链表中没有找到该元素
}//将链表中的字符oldElem改为newElem
void amendElem(component* array, int body, char oldElem, char newElem)
{int add selectElem(array, body, oldElem);if (add -1){printf(无更改元素);return;}array[add].data newElem;
}//输出函数
void displayArr(component* array, int body)
{int tempBody body;//tempBody准备做遍历使用while (array[tempBody].cur){printf(%c,%d \n, array[tempBody].data, array[tempBody].cur);tempBody array[tempBody].cur;}printf(%c,%d\n, array[tempBody].data, array[tempBody].cur);
}int main()
{component array[maxSize];int body initArr(array);printf(静态链表为\n);displayArr(array, body);printf(在第3的位置上插入结点‘e’:\n);insertArr(array, body, 3, e);displayArr(array, body);printf(删除数据域为‘a’的结点:\n);deletArr(array, body, a);displayArr(array, body);printf(查找数据域为‘e’的结点的位置:\n);int selectAdd selectElem(array, body, e);printf(%d\n, selectAdd);printf(将结点数据域为‘e’改为‘h’:\n);amendElem(array, body, e, h);displayArr(array, body);return 0;
}