张赐荣——一位视障程序员。
赐荣小站: www.prc.cx

張賜榮

张赐荣的技术博客

博客园 首页 新随笔 联系 订阅 管理

C语言 实现链表

链表概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比于线性表顺序结构,操作复杂。
由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。
链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。
链表可以在多种编程语言中实现,本文就使用C语言演示实现链表存储结构。


链表初接

#include <stdio.h>
#include <malloc.h>
#define NULL 0
typedef struct node
{
int data;
struct node *next;
}NODE;
int main(void)
{
NODE *head,*p,*q,*r;
head = (NODE *)malloc(sizeof(NODE));
p = (NODE *)malloc(sizeof(NODE));
q = (NODE *)malloc(sizeof(NODE));
head->data = 0;
r = (NODE *)malloc(sizeof(NODE));
p->data = 5;
q->data = 10;
r->data = 20;
head->next = p;
p->next = q;
q->next = r;
r->next = NULL;
printf("%d\n%d\n%d\n",p->data,p->next->data,p->next->next->data);
free(head);
head = NULL;
free(p);
p = NULL;
free(q);
q = NULL;
free(r);
r = NULL;
return 0;
}

/*
先来熟悉几个术语,节点,首节点,尾节点,头节点,头指针;
可以把节点理解成数组中的元素,节点就是链表中的元素。
可以用结构体描述一个存放数据的节点,这个节点至少要包含两个部分,数据部分,称为数据域,指向下一个节点的指针,称为指针域;
数据域可以是任意类型,指针域的类型必须是指向结构体本身的指针类型,一个节点的指针域存放指向下一个节点的内存地址,下一个节点的指针域存放在下一个节点的内存地址,由此可将每个节点串联起来,称为链表;
首节点就是链表中存放有效数据的第一个节点,尾节点就是存放有效数据的最后一个节点,尾节点的指针域指向NULL;
头节点就是首节点前面的节点,因为首节点是存放有效数据的第一个节点,所以头节点不存放有效数据,头节点的指针域指向首节点;
头指针就是头节点的指针;
*/


非循环单链表

// 实现链表的创建、插入、便利、删除、销毁。

#include <stdio.h>
#include <malloc.h>
#define NULL 0
typedef struct node
{
int data;
struct node *next;
}NODE;
NODE *create(void);
void insert(NODE *,NODE *,int);
void delete(NODE *,int);
void print(NODE*);
void Free(NODE *);
int main(void)
{
NODE *head = create();
NODE *a = (NODE *)malloc(sizeof(NODE));
NODE *b = (NODE *)malloc(sizeof(NODE));
NODE *c = (NODE *)malloc(sizeof(NODE));
NODE *d = (NODE *)malloc(sizeof(NODE));
NODE *e = (NODE *)malloc(sizeof(NODE));
a->next = NULL;
b->next = NULL;
c->next = NULL;
d->next = NULL;
e->next = NULL;
a->data = 100;
b->data = 200;
c->data = 300;
d->data = 400;
e->data = 500;
insert(head,a,1);
insert(head,b,2);
insert(head,c,3);
insert(head,d,4);
insert(head,e,1);
delete(head,3);
print(head);
Free(head);
return 0;
}
NODE *create(void)
{
NODE *head = (NODE *)malloc(sizeof(NODE));
NODE *p = (NODE *)malloc(sizeof(NODE));
head->next = p;
head->data = 0;
p->next = NULL;
p->data = 0;
return head;
}
void insert(NODE *head,NODE *pNode,int i)
{
NODE *p = head;
int j = 0;
while(j<i-1&&p)
{
p = p->next;
j++;
}
pNode->next = p->next;
p->next = pNode;
return ;
}
void print(NODE *head)
{
NODE *p = head;
while(p->next)
{
printf("%d\n",p->next->data);
p = p->next;
}
return ;
}
void delete(NODE *head,int i)
{
NODE *p = head,*q;
int j = 0;
while(j<i-1&&p->next!=NULL)
{
p = p->next;
j++;
}
if(!p->next) //节点不存在
return ;
q = p->next;
if(q->next)
{
p->next = q->next;
free(q);
}
else
{
free(q);
p->next = NULL;
}
return ;
}
void Free(NODE *head)
{
NODE *p,*q;
p = head;
while(p->next)
{
q = p->next;
p->next = q->next;
free(q);
}
free(head);
return ;
}

/*
如果尾节点与头节点进行连接,及表示尾节点的指针域指向头节点,这种链表被称为循环链表;
循环单链表可以通过任意一个节点,找到链表所有的节点;
一个节点可以包含两个指针域,指向上一个节点的指针和指向下一个节点的指针,这样的链表叫做双链表;
所以链表分四种,非循环单链表,非循环双链表,循环单链表和循环双链表;
本例实现了非循环单链表的创建,插入,便利,删除,销毁,只是一个基本算法,还存在一些细节问题。
*/


循环单链表

// 通过任意节点实现便利和销毁

#include <stdio.h>
#include <malloc.h>
#define NULL 0
typedef struct node
{
int data;
struct node *next;
}NODE;
void print(NODE *);
void Free(NODE *);
int main(void)
{
NODE *head = (NODE *)malloc(sizeof(NODE));
NODE *a = (NODE *)malloc(sizeof(NODE));
NODE *b = (NODE *)malloc(sizeof(NODE));
NODE *c = (NODE *)malloc(sizeof(NODE));
NODE *d = (NODE *)malloc(sizeof(NODE));
NODE *e = (NODE *)malloc(sizeof(NODE));
NODE *f = (NODE *)malloc(sizeof(NODE));
NODE *g = (NODE *)malloc(sizeof(NODE));
head->next = a;
a->next = b;
b->next = c;
c->next = d;
d->next = e;
e->next = f;
f->next = g;
g->next = head;
head->data = 0;
a->data = 100;
b->data = 200;
c->data = 300;
d->data = 400;
e->data = 500;
f->data = 600;
g->data = 700;
print(d);
printf("\n\n\n\n");
print(b);
Free(f);
return 0;
}
void print(NODE *pNode)
{
NODE *p = pNode;
printf("%d\n",p->data);
while(p->next != pNode)
{
p = p->next;	
printf("%d\n",p->data);
}
return ;
}
void Free(NODE *pNode)
{
NODE *p = pNode,*q;
while(p->next != pNode)
{
q = p->next;
p->next = q->next;
free(q);
}
return ;
}
posted on 2022-03-21 16:36  张赐荣  阅读(86)  评论(0编辑  收藏  举报

感谢访问张赐荣的技术分享博客!
博客地址:https://cnblogs.com/netlog/
知乎主页:https://www.zhihu.com/people/tzujung-chang
个人网站:https://prc.cx/