一、单向链表的特征
单向链表是利用动态内存分布、使用结构体并配合指针来实现的一种数据结构。相比于数组,单向链表进行数据插入和删除的操作更为简单,但是,调取链表中的元素,只能一个个去访问寻找,不能直接通过位置,一步得到。
二、实现单向链表的基础
struct student
{
int score;
char num[100];
struct student *next;/*通过这个可以指向结构体的指针,可以将多个结构体像是锁链一样连起来
例如:p1->p2->p3->NULL 注:链表最后一个元素的next是指向空指针的*/
};
单向链表通过结构体中,放一个指向本结构体的指针成员,来实现,将每一个元素像锁链一样串起来。
三、创建一个链表
typedef struct student
{
int score;
char num[100];
struct student *next;
}STU;我们可以通过typedef来将struct student用STU来替代,减少代码量
STU *Creatlink(STU a[] , int n)
//定义一个结构体类型的返回指针的函数,链表最后实际上是返回链表的头指针
{
STU *head;// 定义一个student结构类型的指针,作为链表的头指针
head = &a[0];//将结构体数组的第一个元素的位置给头指针
// 用循环将链表串连起来
for(int i = 0 ; i < n - 1 ; i++)
{
a[i].next = &a[i + 1];
}
a[n - 1].next = NULL;//最后一个指向空指针
return head;//最后返回头指针
}
我们通过上述返回指针的函数,得到了完成了链表的串联,同时,返回了该链表的头指针,我们可以通过操作链表的头指针来操作整个链表。
四、实现在一个链表中查找元素
在单向链表中,要是需要查找某一个元素,我们从链表的第一个元素开始向下遍历,直到找到那个元素为止。
void Find(STU *head , char num[])//根据学号找人
{
STU *p = head;// 用一个p指针来储存头指针,防止head发生变化
while(p != NULL)
{
if(strcmp(p->num,num) == 0) break;
p = p->next;// 传向下一个指针
}
if(p == NULL) printf("查无此人");
else //说明找到了
{
printf("%d %s", p->score , p->num);
}
}
五、实现删除链表中的一个元素
在单向链表中,删除一个元素,实际操作就是将待删除元素的上一个元素与下一个元素相连,直接跳过这个元素,达到删除的效果。
STU *Dely(STU *head , char num[])
{
STU *p = head , *front;//用front储存前一个指针;
while(p != NULL)
{
if(strcmp(p->num,num) == 0) break;
}
front = p;
p = p->next;
if(p != NULL) // 说明找到了要删除的人
{
front->next = p->next;
}
return head;//同过返回头指针返回变化后的链表
}
删除之后得到一个新链表,故返回head。
六、实现在单向链表中添加一个元素
在单向链表中,添加一个元素又三种情况:
(1)直接添加在链表的最前面,就是将该元素与原链表第一个元素相连,然后,将该元素的位置变为head;
(2)添加在链表的末尾,就是将该元素与原链表的最后一个元素相连,同时,还要将该元素的末尾连上空指针NULL;
(3)添加在链表的中间,将是将该元素与所需要插入位置的前一个,还有后一个元素同时相连;
以上三种情况都会生成一个新的链表,故均会返回head;
下面以向链表中按年龄顺序插入一个元素为例:
STU *insert(STU *head , STU *pnewnode)
{
STU *p , *front;
p = head;
while(p != NULL && p->score < (pnewnode->score))//p指向节点的分数比newnode所指向的节点分数小就一直往后移
{
front = p;
p = p->next;
}
if(p == head)
{
pnewnode->next = head;
head = pnewnode;//新节点排在head前面,所以newnode成了新head
}
else
{
if(p == NULL) //说明插到末尾
{
front->next = pnewnode;//把储存的位置给下一个连上新节点
pnewnode->next = NULL;//新节点的下一个连上NULL
}
else//说明是在中间插入;
{
front->next = pnewnode;
pnewnode->next = p;
}
}
return head;
}
最后,给大家一个实现上述功能的总代码:
#include<>
#include<>
typedef struct student
{
int score;
char num[100];
struct student *next;
}STU;
//创建一个链表
STU *Creatlink(STU a[] , int n)
{
STU *head;
head = &a[0];
for(int i = 0 ; i < n - 1 ; i++)
{
a[i].next = &a[i + 1];
}
a[n - 1].next = NULL;
return head;
}
//实现一个链表的查找
void Find(STU *head , char num[])
{
STU *p = head;
while(p != NULL)
{
if(strcmp(p->num,num) == 0) break;
p = p->next;
}
if(p == NULL) printf("查无此人");
else
{
printf("%d %s", p->score , p->num);
}
}
//链表中元素的删除
STU *Dely(STU *head , char num[])
{
STU *p = head , *front;
while(p != NULL)
{
if(strcmp(p->num,num) == 0) break;
}
front = p;
p = p->next;
if(p != NULL)
{
front->next = p->next;
}
return head;
}
//链表的插入
STU *insert(STU *head , STU *pnewnode)
{
STU *p , *front;
p = head;
while(p != NULL && p->score < (pnewnode->score))
{
front = p;
p = p->next;
}
if(p == head)
{
pnewnode->next = head;
head = pnewnode;
}
else
{
if(p == NULL)
{
front->next = pnewnode;
pnewnode->next = NULL;
}
else
{
front->next = pnewnode;
pnewnode->next = p;
}
}
return head;
}
void output(STU *head)
{
struct student *p = head;
while(p != NULL)
{
printf("%d %s\n", p->score , p->num);
p = p->next;
}
}
int main()
{
int n;
scanf("%d", &n);
STU a[100];
for(int i = 0 ; i < n ; i++)
{
scanf("%d %s", &a[i].score , &a[i].num);
}
STU *pnewnode , *head , newnode;
scanf("%d %s", & , &);
pnewnode = &newnode;
char num1[100] , num2[100] , num3[100];
scanf("%s %s %s", &num1 , &num2 , &num3);
head = Creatlink(a , n);
output(head);
Find(head , num1);
head = Dely(a ,num2);
output(head);
head = insert(a , pnewnode);
output(head);
return 0;
}