顺表的介绍与基本操作

本文介绍了链表相关知识,链表是物理存储非连续、非顺序,靠指针链接实现逻辑顺序的存储结构,共分8种,常见的有不带头非循环单链表、带头循环双向链表。还阐述了带头结点和不带头结点的区别,以及链表的基础操作,如头删、头插等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 熟悉什么是链表,链表的分类?
    链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
    链表一共分为8种。1.单向、双向。2.带头、不带头。3.循环、不循环。由这几种情况组合而成。
    https://blog.youkuaiyun.com/a331683772/article/details/89577728

常见的是不带头非循环单链表、带头循环双向链表。
2. 熟悉链表带头结点和不带头结点的区别?
带头节点,用一个特殊的节点存放指向链表第一个元素的指针,如果该指针为空就说明该链表没有节点,为空链表。
不带头节点,第一个元素包含数据和指向下一个元素的指针。它就是该链表的起点。
3.链表的基础操作!
链表的头文件 在其中定义了节点,变量类型Node代表节点为这个节点的实体,PNode为指向的Node的指针**,用于操作。**

#pragma once
typedef int SDataType;
typedef struct SlistNode
{
 SDataType _data;
 struct SlistNode* _pNext;
}Node,*PNode;   // Node  和 *PNode 相当与是  SlistNode类型的变量
                // 链表的结构,给一个头指针保存链表第一个节点的地址
typedef struct SList
{
 PNode _pHead; // 指向链表中的第一个节点 
}SList, *PSList;
// 链表的初始化 
void SListInit(SList* s);
// 在链表s最后一个节点后插入值为data的节点 
void SListPushBack(SList* s, SDataType data);
// 删除链表s最后一个节点 
void SListPopBack(SList* s);
// 在链表s第一个节点前插入值为data的节点 
void SListPushFront(SList* s, SDataType data);
// 删除链表s的第一个节点 
void SListPopFront(SList* s);
// 在链表的pos位置后插入值为data的节点 
void SListInsert(PNode pos, SDataType data);
// 删除链表s中pos位置的节点 
void SListErase(SList* s, PNode pos);
// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFind(SList* s, SDataType data);
// 获取链表中有效节点的个数 size_t SListSize(SList* s);
// 检测链表是否为空 
int SListEmpty(SList* s);
// 将链表中有效节点清空 
void SListClear(SList* s);
// 销毁链表 
void SListDestroy(SList* s);

链表的基本操作如下:该程序为有头节点,先定义一个头,头中包含一个指针_pHead指向第一个节点。将其置为空表示该链表里面还没有值。形参s要检测是否为空,因为s为空和链表为空为两个不同的概念。
头删 头插 尾删 尾插都很简单,值得注意的是中间的插入和删除,先用寻找函数找到位置,然后再用删除函数删除。
在使用while的时候要考虑如果传错值的时候程序是否还能正常运行。

# include"标头.h"
# include<assert.h>
# include<malloc.h>
# include<stdio.h>
//节点的初始话
void SListInit(SList* s)
{
 assert(s);
 s->_pHead = NULL;
}
//创建新的节点
PNode BuySListNode(SDataType data)
{
 PNode pNewNode =(PNode) malloc(sizeof(Node));  //malloc创建的空间返回指针为Node*  需要转化为PNode
 if (NULL == pNewNode)
 {
  assert(0);
  return NULL;
 }
 pNewNode->_data = data;
 pNewNode->_pNext = NULL;
 return pNewNode;
}
//头插
void SListPushFront(SList* s,SDataType data)
{
 assert(s);
 if (s->_pHead == NULL) {
  SListPushBack(s, data);
 }
 else
 {
 PNode pNewNode= BuySListNode(data);
 pNewNode->_pNext = s->_pHead;
 s->_pHead->_pNext = pNewNode;
 }
}
//头删
void  SListPopFront(SList* s)
{
 assert(s);
 if (NULL==s->_pHead)
 {
  return;
 }
 PNode pDelNode = s->_pHead;
 s->_pHead = s->_pHead->_pNext;
 free(pDelNode);
 }
//尾插
void SListPushBack(SList* s, SDataType data)
{
 assert(s);
 PNode pNewNode = BuySListNode(data); //创建一个新的节点
 if (NULL == s->_pHead)  //如果链表为空,则让头节点直接指向新建立的节点
 {
  s->_pHead = pNewNode;
 }
 else
 {
  PNode pCur = s->_pHead;//创建一个变量用于需寻找 将其指针的值设为一个节点
  while (pCur->_pNext)       //搜索最后一个节点为空时停下
  {
   pCur=pCur ->_pNext; //容易写出pCur->_pNext;  这样以来一直在读取自己的下一个元素 而不是下一个的下一个元素
  }
  pCur->_pNext = pNewNode;
 }
}
//打印函数
void PritfSList(SList* s)
{
 assert(s);
 if (s->_pHead==NULL)
 {
  printf("NULL\n");
  return;
 }
 PNode pCur = s->_pHead;
   while (pCur)  //pCur->_pNext容易写成  这个是下一个元素  pCur表示的是当前元素 
   {             //上面这个写法会少打印一个元素
    printf("%d----->", pCur->_data);
    pCur = pCur->_pNext;
   }
   printf("NULL\n");
}
//尾删
void SListPopBack(SList* s)
{
 assert(s);
 PNode pCur = s->_pHead;
 if (pCur==NULL)
 {
  return;
 }
 if (pCur->_pNext==NULL)
 {
  free(pCur);
  s->_pHead = NULL;
  return;
 }
 while (pCur->_pNext->_pNext)    //利用下一个元素的指针找到下下一个元素
 {
  pCur = pCur->_pNext;
 }
 free(pCur->_pNext );  //删除指针后需要将其滞空
 pCur->_pNext = NULL;   //找到之后将其删除
}
//删除指定位置的节点
void SListEarse(SList* s,PNode pos)
{
 assert(s);
 if (NULL==pos||NULL==s->_pHead)
 {
  return;
 }
 if (pos == s->_pHead)
 {
  s->_pHead = s->_pHead->_pNext;
 }
 else
 {
  PNode pPrePos = s->_pHead;
  while (pPrePos && pPrePos->_pNext!=pos)
  {
   pPrePos = pPrePos->_pNext;
  }
  if(pPrePos)
  pPrePos->_pNext = pPrePos->_pNext->_pNext;
 }
 free(pos);
}
//指定位置插入节点
void  SlistInsert(PNode pos,SDataType data)   //PNode 表示的是一个节点的位置 位置给后节点的地址就有了
{
 if (pos==NULL)                    {
  return;
 }
 PNode pNewNode = BuySListNode(data);
 pNewNode->_pNext = pos->_pNext;
 pos->_pNext = pNewNode;
}
// 找到该元素的位置并返回指针以方便下面的计算
PNode SListFind(SList* s, SDataType data)
{
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur)
 {
  if (pCur->_data == data)
  {
   return pCur;
  }
  pCur = pCur->_pNext;
 }
 return NULL;
}
//计算节点的个数
size_t SlistSize(SList* s)
{
 assert(s);
 PNode pCur = s->_pHead;
 size_t count = 0;
 while (pCur)
 {
  count++;
  pCur = pCur->_pNext;
 }
 return count;
}
int SListEmpty(SList* s)
{
 assert(s);
 return NULL == s->_pHead;
}
//测试函数
void TestList2()
{
 SList S;
 SListInit(&S);
 SListPushBack(&S, 1);
 SListPushBack(&S, 3);
 SListPushBack(&S, 2);
 PritfSList(&S);
 printf("一共有%d\n",  SlistSize(&S));
 SListEarse(&S, SListFind(&S, 0));
 PritfSList(&S);
 SlistInsert(SListFind(&S,3), 6);
 PritfSList(&S);
}
void TestList()
{
 printf("\n\n\n");
 TestList2();
}
int main()
{
 TestList();
 system("pause");
 return 0;
}
内容概要:该论文聚焦于T2WI核磁共振图像超分辨率问题,提出了一种利用T1WI模态作为辅助信息的跨模态解决方案。其主要贡献包括:提出基于高频信息约束的网络框架,通过主干特征提取分支和高频结构先验建模分支结合Transformer模块和注意力机制有效重建高频细节;设计渐进式特征匹配融合框架,采用多阶段相似特征匹配算法提高匹配鲁棒性;引入模型量化技术降低推理资源需求。实验结果明,该方法不仅提高了超分辨率性能,还保持了图像质量。 适合人群:从事医学图像处理、计算机视觉领域的研究人员和工程师,尤其是对核磁共振图像超分辨率感兴趣的学者和技术开发者。 使用场景及目标:①适用于需要提升T2WI核磁共振图像分辨率的应用场景;②目标是通过跨模态信息融合提高图像质量,解决传统单模态方法难以克服的高频细节丢失问题;③为临床诊断提供更高质量的影像资料,帮助医生更准确地识别病灶。 其他说明:论文不仅提供了详细的网络架构设计实现代码,还深入探讨了跨模态噪声的本质、高频信息约束的实现方式以及渐进式特征匹配的具体过程。此外,作者还对模型进行了量化处理,使得该方法可以在资源受限环境下高效运行。阅读时应重点关注论文中提到的技术创新点及其背后的原理,理解如何通过跨模态信息融合提升图像重建效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值