C语言单链表存储详解:从原理到完整代码实现
顺序表依赖连续的内存空间,而单链表通过指针将随机分配的内存节点串联起来,形成线性的逻辑结构。掌握单链表的核心在于理解头指针与结点的关系。
单链表的存储不要求物理地址连续,而是依靠每个结点内部包含的指针域指向下一个结点的地址来实现前后关联。
理解单链表的基本构成是编写代码的前提:
- 头指针:保存第一个节点的地址,通常用于代表整个链表。
- 头结点(可选):位于首元结点之前的空节点,主要用于简化插入或删除操作。
- 首元结点:存放实际数据的第一个节点。
第一步:定义链表结点结构
目的是建立数据域与指针域的载体。在C语言中,通常使用 struct 来定义结点,其中包含一个数据成员和一个指向同类型结构体的指针成员。
typedef struct Link{
char elem; // 数据域
struct Link *next; // 指针域,指向后继元素
}link; // link为节点别名第二步:初始化单链表
初始化的过程即动态创建结点并建立连接的过程。根据是否设置“头结点”,实现逻辑略有不同。
方法一:带头结点的初始化
创建一个空的头结点,然后通过循环依次创建新结点并将其挂载在末尾。这种方式使得对首元结点的处理与其他结点一致。
link * initLink(){
link *p=(link*)malloc(sizeof(link)); // 创建头结点
link*temp = p; // temp作为移动指针,当前指向头结点
for(int i=1;i<5;i++) // 循环创建4个数据结点
{
link *a=(link*)malloc(sizeof(link)); // 生成新结点
a->elem=i; // 赋值
a->next=NULL; // 尾结点的next置空
temp->next=a; // 前驱结点指向新结点
temp=temp->next; // 临时指针后移
}
return p; // 返回头结点指针
}方法二:不带头结点的初始化
直接创建首元结点并让头指针指向它,后续结点按相同逻辑追加。此方式节省了一个结点的内存,但处理首个位置的插入或删除时需特殊判断。
link * initLink2(){
link *p=NULL; // 定义头指针初始为空
link*temp=(link*)malloc(sizeof(link)); // 创建首元结点
temp->elem=1; // 首元结点初始化
temp->next=NULL;
p=temp; // 头指针指向首元结点
for(int i=2;i<5;i++){ // 从第二个数据开始循环
link *a=(link*)malloc(sizeof(link));
a->elem=i;
a->next=NULL;
temp->next=a; // 建立逻辑链接
temp=a; // 后移
}
return p; // 返回头指针
}第三步:遍历并输出链表数据
通过修改临时指针的移动条件,可以实现对不同结构链表的读取。
带头结点的输出函数
只要当前结点的后继指针不为空,就移动到下一个结点并打印数据。
void display(link *p){
link*temp=p;
while(temp->next){ // 遇到最后一个结点的next为空时停止
temp=temp->next;
printf("%d ",temp->elem);
}
printf("\n");
}不带头结点的输出函数
直接从当前结点开始打印,直到指针本身变为 NULL。
void display2(link *p){
link* temp=p;
while (temp) { // 指针本身非空即继续
printf("%d ",temp->elem);
temp=temp->next;
}
printf("\n");
}第四步:整合完整代码与验证
将上述功能整合至主函数中进行测试,观察输出是否符合预期。
#include#include typedef struct Link{ int elem; struct Link *next; }link; // ... 此处省略initLink, display等辅助函数的完整实现,参考上方第二步和第三步的代码块 ... int main() { display(initLink()); return 0; }
执行编译后的程序,控制台将依次打印出1到4的整数序列。
以上就是C语言数据结构之单链表存储详解的详细内容,更多关于C语言单链表存储的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













