C语言的链表也是一个很重要很难啃的骨头,我是这么觉得的!
以下只是个人对链表的总结和记录方便日后复习所用,如有错误,请留言狠批,谢谢!
先说下链表的简单实现:
如上图,我们定义一个结构体:
1,2,3,4,5是结构体数据。a,b,c,d,e则是指针变量,在链表中是1.next的表达方式
首先,结构体的名字指向的是链表的首地址(也就是1的地址,而a的存放是2的地址),这样指下去。一个简单的列表就形成了。需要注意的是,链表最后的数据中e的位置需要指向NULL,这样才使得链表暂时时结束的。后面我们还会学到对链表的增、删、查等操作!
下面我们就定义了一个简单的链表,并给链表赋值,并打印值
/*
链表的简单实现
*/
struct Stu
{
long num;
double score;
struct Stu *next;
};
void main()
{
struct Stu a, b, c, *head;
a.num = 10001;
a.score = 98;
b.num = 10002;
b.score = 89;
c.num = 10003;
c.score = 90;
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
do {
printf("%d %5.2f\n", head->num, head->score);
head = head->next;
} while (head!=NULL);
}
上面赋值和查数据都可以了
链表的插入:
(三种情况,最前面插入。中间插入。最后面插入)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct Stu) //宏定义,利用sizeof求出结构体的大小。方便我们在代码中向内存要空间
int n; //总共输入的学生统计
struct Stu //定义一个学生结构体
{
long num; //学号
double score;//分数
struct Stu *next;//指向下一个的指针
};
struct Stu *create(); //创建链表
void print(struct Stu *head);//打印链表
struct Stu *insert(struct Stu *head, struct Stu *insert); //插入链表
void main()
{
struct Stu *stu,*p, sert; //输入数据创建一个链表,并打印出来
stu = create();
p = stu;
print(p);
printf(" Here please create need insert is data \n");
//输入要插入的数据
printf("please input stu num:");
scanf_s("%d", &sert.num);
printf("please input stu score:");
scanf_s("%lf", &sert.score);
p = insert(stu, &sert);
print(p);
printf("insert data OK;");
}
struct Stu *create()
{
//原理:先定义三个指针变量,p1和p2默认向内存求取了一个结构体大小的空间,head默认指向空地址
//接收用户第一次输入的学号和分数,存进p1的num和score中
//while循环,只要用户输入的学号不为0,程序继续
struct Stu *head, *p1, *p2;
p1 = p2 = (struct Stu *)malloc(LEN);
printf("please input stu num:");
scanf_s("%d", &p1->num);
printf("please input stu score:");
scanf_s("%lf", &p1->score);
head = NULL;
while (0 != p1->num)//如果输入的学号为0,程序结束停止接受用户输入新的学员信息
{
n++;
if (1 == n)
{
//当n==1时。则说明是第一个学生的信息,把head指向第一个学生
head = p1;
}
else
{
//已经是第二个学生和以后的学生信息了,就先把用户刚输入的信息放入p2的next
p2->next = p1;
}
//把用户刚输入的信息p1的值赋值给p2
p2 = p1;
//p1从新再接收用户的输入
p1 = (struct Stu *)malloc(LEN);
printf("please input stu num:");
scanf_s("%d", &p1->num);
printf("please input stu score:");
scanf_s("%lf", &p1->score);
}
//用户输入的学号为0,循环结束,则把当前最后的,也就是指向最后用户输入的信息的p2的next指向NULL,结束链表创建
p2->next = NULL;
//返回链表的头指针
return head;
}
void print(struct Stu *head)
{
struct Stu *p;
p = head;
if (NULL != head)
{
do
{
printf("%d %lf\n", p->num, p->score);
p = p->next;
} while (NULL != p);
}
printf("\n");
}
struct Stu *insert(struct Stu *head, struct Stu *insert)
{
//定义三个指针,p指向传进来的原有链表的头地址,p1指向需要插入的链表头地址
struct Stu *p, *p1, *p2;
p = head;
p1 = insert;
p2 = NULL;
//先判断需要插入的学生学号p1->num大于原有的链表头p->num的,并且p的next不等于NULL,也就是不是空链表
while (p1->num > p->num && NULL != p->next)
{
p2 = p;
p = p->next;
}
//要插入的学生学号p1->num小于等于原有的链表头p->num的,又分两种情况
if (p1->num <= p->num)
{
//等于
if (head = p)
{
head = p1;
}
//小于。也就是放入原有链表的最前面
else
{
p2->next = p1;
}
p1->next = p;
}
else
{
//放入原有链表的最后面
p->next = p1;
p1->next = NULL;
}
return head;
}
链表的删除:
(删除比插入稍微简单点。只需要把要删除的前一个的.next指向需要删除的数据的.next指向的地址)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct Stu)
struct Stu
{
long num;
double score;
struct Stu *next;
};
//创建链表
struct Stu *create();
//打印链表
void print(struct Stu *head);
//删除链表里面指定的学号的数据
struct Stu *del(struct Stu *head, long num);
int n;
void main()
{
//创建链表
struct Stu *stu;
long m;
stu = create();
//打印链表
print(stu);
//删除指定学号的链表,再次打印
printf("please delete is num:");
scanf_s("%d", &m);
print(del(stu, m));
printf("\n");
system("pause");
}
//创建链表
struct Stu *create()
{
struct Stu *head, *p1, *p2;
p1 = p2 = (struct Stu *)malloc(LEN);
printf("pleast is num:");
scanf_s("%d", &p1->num);
printf("please is score:");
scanf_s("%lf", &p1->score);
head = NULL;
n = 0;
while (0 != p1->num)
{
n++;
if (1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct Stu *)malloc(LEN);
printf("pleast is num:");
scanf_s("%d", &p1->num);
printf("please is score:");
scanf_s("%lf", &p1->score);
}
p2->next = NULL;
return head;
}
//打印链表
void print(struct Stu *head)
{
struct Stu *p;
p = head;
if (NULL != head)
{
do
{
printf("%d %lf\n", p->num, p->score);
p = p->next;
} while (NULL != p);
}
printf("\n");
}
//删除链表里面指定的学号的数据
struct Stu *del(struct Stu *head, long num)
{
struct Stu *p1 ,*p;
p = head;
p1 = NULL;
if (NULL == head)
{
goto End;
}
while(p->num != num && NULL != p->next)
{
p1 = p; //在向后移的时候记录下来
p = p->next; //向后接着找
}
if (p->num == num)
{
if (p == head)
{
head = p->next;
}
else {
p1->next = p->next;
}
}
End:
return head;
}