链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。
链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。
说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
创建链表:
typedef struct Node
{
int data;
struct Node *next;
} Node;
//创建链表
void createLink(Node *head, int size)
{
Node *rear = head;
int i;
for (i = 0; i < size; ++i)
{
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->next = NULL;
scanf("%d", &newnode->data);
rear->next = newnode;
rear = newnode;
}
}
int mian()
{
Node *head = (Node *)malloc(sizeof(Node));
head->next = NULL;
createLink(head, 10); //创建链表
}
删除链表节点:
void delet(Node *head, int n)
{
Node *in;
int i = 0;
while (i < n && head != NULL)
{
in = head;
head = head->next;
i++;
}
if (head != NULL)
{
in->next = head->next;
free(head);
}
else
{
puts("节点不存在");
}
}
插入链表节点:
void insertLink(Node *head, int n)
{
int i = 0;
while (i < n && head != NULL)
{
head = head->next;
i++;
}
if (head != NULL)
{
Node *newnode = (Node *)malloc(sizeof(Node));
printf("输入要插入的值:");
scanf("%d", &newnode->data);
newnode->next = head->next;
head->next = newnode;
}
else
{
printf("节点不存在");
}
}
示例代码:
//链表创建、头插、尾插、删除、翻转、删除相同元素、遍历、判断链表是否为空
#include
#include
typedef struct Node
{
int data;
struct Node *next;
} Node;
//创建链表
void createLink(Node *head, int size)
{
Node *rear = head;
int i;
for (i = 0; i < size; ++i)
{
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->next = NULL;
scanf("%d", &newnode->data);
rear->next = newnode;
rear = newnode;
}
}
//遍历链表
void travelLink(Node *head)
{
Node *p = head->next;
while (p != NULL)
{
printf("%d\t", p->data);
p = p->next;
}
putchar('\n');
}
//头插法
void insertForward(Node *head, int data)
{
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->next = NULL;
newnode->data = data;
newnode->next = head->next;
head->next = newnode;
}
//尾插法
void insertBack(Node *head, int data)
{
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->next = NULL;
newnode->data = data;
Node *p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = newnode;
p = newnode;
}
//在第N个元素后插入元素
void insertLink(Node *head, int n)
{
int i = 0;
while (i < n && head != NULL)
{
head = head->next;
i++;
}
if (head != NULL)
{
Node *newnode = (Node *)malloc(sizeof(Node));
printf("输入要插入的值:");
scanf("%d", &newnode->data);
newnode->next = head->next; //填充newnode节点的指针域,也就是说把in的指针域指向newnode的下一个节点
head->next = newnode; //填充t节点的指针域,把t的指针域重新指向in
}
else
{
printf("节点不存在");
}
}
//删除相同元素
void deleteSame(Node *head)
{
Node *curr = head->next;
while (curr != NULL)
{
Node *pre = curr;
Node *p = curr->next;
while (p != NULL)
{
//若有相同的元素,则删除;否则两个指针继续向下走
if (curr->data == p->data)
{
pre->next = p->next;
free(p);
p = pre->next;
}
else
{
pre = pre->next;
p = p->next;
}
}
curr = curr->next;
}
}
//删除第N个元素
void delet(Node *head, int n)
{
Node *in;
int i = 0;
while (i < n && head != NULL)
{
in = head;
head = head->next;
i++;
}
if (head != NULL)
{
in->next = head->next;
free(head);
}
else
{
puts("节点不存在");
}
}
//翻转链表
void reverseLink(Node *head)
{
Node *curr;
Node *pre = NULL;
while (head->next != NULL)
{
curr = head->next;
head->next = curr->next;
curr->next = pre;
pre = curr;
}
head->next = pre;
}
//删除链表
void deleteLink(Node *head)
{
Node *curr;
while (head->next != NULL)
{
curr = head->next;
head->next = curr->next;
free(curr);
}
}
//判断链表是否为空
void isEmpty(Node *head)
{
if (head->next == NULL)
{
printf("链表为空!\n");
}
else
{
printf("链表不为空!\n");
}
}
int main()
{
//主函数中不能指定一个头指针,应该定义一个头指针指向头结点
Node *head = (Node *)malloc(sizeof(Node));
head->next = NULL;
printf("输入元素:\n");
createLink(head, 10); //创建链表
printf("遍历链表:");
travelLink(head); //遍历链表
printf("头插法:");
insertForward(head, 100); //头插法
travelLink(head); //遍历链表
printf("尾插法:");
insertBack(head, 200); //尾插法
travelLink(head); //遍历链表
printf("删除相同元素:");
deleteSame(head); //删除相同元素
travelLink(head); //遍历链表
printf("删除第5个元素:");
delet(head, 5);
travelLink(head); //遍历链表
printf("在第3个元素后插入元素,");
insertLink(head, 3); //插入元素
travelLink(head); //遍历链表
printf("翻转链表元素:");
reverseLink(head); //翻转链表元素
travelLink(head); //遍历链表
printf("删除链表:");
deleteLink(head); //删除链表
isEmpty(head); //判断链表是否为空
return 0;
}
测试结果:
参考文章:c语言链表详解(超详细)_Mr.Gzj的博客-CSDN博客_链表c语言