链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
在这里我们直接来看案例:
#include "linklist.h"
#include "linklist.h"
#include <stdio.h>
#include <stdlib.h>
// 创建链表
// data,数据数组
// data_length,数组长度
struct LinkList *linklist_create(int data[], int data_length)
{
struct LinkList *head;
struct LinkList *tail;
int i;
// 创建并初始化头结点
head = (struct LinkList *)malloc(sizeof(struct LinkList));
head->id = -1;
head->next = NULL;
tail = head;
for (i = 0; i < data_length; i++) {
// 1)创建节点并初始化
struct LinkList *node;
node = (struct LinkList *)malloc(sizeof(struct LinkList));
node->id = data[i];
node->next = NULL;
// 2)尾结点连接新节点
tail->next = node;
// 3)尾结点移动到新节点
tail = node;
}
return head;
}
// 遍历链表,打印
void linklist_printf(struct LinkList *head)
{
struct LinkList *p;
// for (i = 0; i < n; i++)
for (p = head; p != NULL; p = p->next)
{
printf("%d\n", p->id);
}
}
// return 0成功,-1失败
int linklist_delete(struct LinkList *head, int id)
{
struct LinkList *prev;
struct LinkList *del;
prev = head;
// 1)找到待删除节点的上一个节点
while(prev != NULL && prev->next != NULL) {
if (prev->next->id == id) {
break;
}
prev = prev->next;
}
// 没找到id
if (prev->next == NULL) {
return -1;
}
// 2)删除节点
// 2.1)临时保存待删除节点del
del = prev->next;
// 2.2)从链表删除节点del
prev->next = del->next;
// 2.3)free del
free(del);
return 0;
}
在这个例子中有创建链表和遍历链表。在创建链表中我们创建了struct LinkList *head;
struct LinkList *tail;用来保存头指针和尾指针。尾指针在不断的行进中创建一条链表。在实现遍历的时候也是一样的道理。因为在链表的没有给个结构体中都有着链表中下一个结构体的地址。我们只依次访问便可以遍历链表。我们只要获取头指针的地址即可。
接下来这个是集合创建、删除、添加以及替换的范例
linklist.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Student {
int num;
struct Student *pnext;
};
struct Student * init();
void stuput(struct Student *stu);
struct Student *delete (struct Student *stu);
struct Student *jia(struct Student *stu) ;
struct Student *h1(struct Student *stu);
#endif
demo1.c(名字自己顺手起的)
#ifndef __DEMO1_H__
#define __DEMO1_H__
#include<stdio.h>
#include<stdlib.h>
#include "linklist.h"
struct Student *init() {//链表的初始化
struct Student *Stu;
struct Student *head;
struct Student *node;
struct Student *tail;
head = (struct Student *)malloc(sizeof(Stu));
head->num = 1;
head->pnext = NULL;
tail = head;
int i;
for (i = 0; i < 4; i++) {
node = (struct Student *)malloc(sizeof(Stu));
node->num = i + 2;
node->pnext = NULL;
tail->pnext = node;
tail = node;
}
return head;
}
void stuput(struct Student *stu) {//链表的输出
struct Student *p;
p = stu;
int i;
for (i = 0; p != NULL; i++) {
printf("num=%d\n ", p->num);
p = p->pnext;
}
}
struct Student *delete (struct Student *stu) {//链表的删除
struct Student *temp;
struct Student *p;
int i;
p = stu;
temp = (struct Student *)malloc(sizeof(stu));
temp->num = 0;
temp->pnext = NULL;
for (i = 0; p != NULL; i++) {
if (p->pnext != NULL && p->pnext->num == 3) {
temp = p->pnext;
p->pnext = temp->pnext;
free(temp);
}
p = p->pnext;
}
return stu;
}
struct Student *jia(struct Student *stu) {//链表的添加
struct Student *p;
struct Student *new;
int i;
p = stu;
new = (struct Student *)malloc(sizeof(stu));
new->num = 0;
new->pnext = NULL;
for (i = 0; p != NULL; i++) {
if (p->pnext != NULL && p->pnext->num == 2) {
new->pnext = p->pnext;
p->pnext = new;
new->num = 9;
break;
}
p = p->pnext;
}
return stu;
}
struct Student *h1(struct Student *stu)//链表的替换
{
struct Student *p;
struct Studnet *k;
int i;
p=stu;
k=NULL;
for(i=0;p!=NULL;i++)
{
if(p->num==5)
{
p->num=44;
}
p=p->pnext;
}
return stu;
}
#endif
main.c
#include "linklist.h"
int main() {
struct Student *stu;
struct Student *p;
struct Student *k;
struct Student *u;
stu = init();
stuput(stu);
printf("===");
p = delete (stu);
stuput(p);
printf("===");
k = jia(stu);
printf("===");
stuput(k);
u = h1(stu);
printf("===");
stuput(u);
return 0;
}
在main.c中,它只负责调用函数。其主要功能由demo1.c内的内容来完成。总的来说,对链表的操作基本上都是基于对与链表的遍历来的。在该范例中,唯独删除与众不同。其余操作皆是需要去遍历链表并寻找符合要求的那一项,并对它进行操作。然而删除却是对目标项的前一项进行操作,由目标项的前一项获取到目标项的地址,并赋值给tmp。由对tmp进行操作,达到删除的目的。