what?(链表是什么)
1.链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
2.由一系列节点组成,节点在使用时可以动态生成。每个节点包括数据域和指针域。
3.相比于数组创建复杂,但是使用起来更加方便(增删改查),并且事先可以不用知道节点的个数。
4.分为有头结点和无头结点类型,区别在于有头结点的链表多出了一个节点放头指针的地址,而数据域为空,使得操作起来更加便捷。
About?(都与些函数有关)
1.malloc()---动态分配一段内存空间
原型为:void*malloc(unsigned int size)
功能为:在内存的动态存储区申请一个长度为size字节的连续存储空间
2.calloc()---动态分配连续内存空间
原型为:void*calloc(unsigned int n,unsigned int size)(n 为元素的个数,size为元素存储长度)
功能为:申请n个长度为size的存储空间
3.realloc()---改变指针指向空间大小
原型为:void*realloc(void *ptr,size_t size)
功能为:改变指针ptr指向大小为size的空间
4.free()---释放存储空间
原型为:void free(void *p)
功能为:将p指向的空间释放,交还给系统。
以上函数使用库函数:#include<stdlib.h>,1也可以使用#include<malloc.h>.
How?(常用的操作---基于有头节点的链表)
1.单链表的创建---有头结点
(1)尾插---源代码
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node*next;
}node,*linklist;
node *creat()
{
linklist L;
node *r,*s;
int n;
L=r=(node *)malloc(sizeof(node));
L->next=NULL;
printf("请输入数据:");
while(1)
{
scanf("%d",&n);
if(n!=0)
{
s=(node *)malloc(sizeof(node));
s->data=n;
r->next=s;
s->next=NULL;
r=s;
}
else
break;
}
return L;
}
void Output(linklist L)
{
node *p;
p=L->next;
while(p)
{
printf("%d\t",p->data);
p=p->next;
}
}
int main()
{
linklist L;
L=creat();
Output(L);
}
此段代码可以实现链表的尾插,建立了两个函数,分别是创建和输出,括号中的!=0为结束条件,读者可以根据需要改变,创建时选择了尾插,原理如下:
每次生成一个节点之后,让前一个节点只想新节点,新节点的指向为NULL,然后将新节点赋给原来的最后一个节点,这样做的目的是统一变量,方便循环的使用。
当然也可以进行头插,不过这样做之后,输出来的数据是倒序的。代码如下:
(2)头插---核心代码
node *creat()
{
linklist L;
node *r,*s;
int n;
L=r=(node *)malloc(sizeof(node));
L->next=NULL;
printf("请输入数据:");
while(1)
{
scanf("%d",&n);
if(n!=0)
{
s=(node *)malloc(sizeof(node));
s->data=n;
s->next=L->next;
L->next=s;
}
else
break;
}
return L;
}
2.单链表的增加
(1)头插法---核心代码:
void Add(linklist L)
{
node *p;
p=(node *)malloc(sizeof(node));
printf("请输入要添加的数:");
scanf("%d",&p->data);
p->next=L->next;
L->next=p;
}
(2)尾插法---核心代码
void Add(linklist L)
{
node *p,*r;
r=L->next;
while(r->next)
{
r=r->next;
}
p=(node *)malloc(sizeof(node));
printf("请输入要添加的数:");
scanf("%d",&p->data);
r->next=p;
p->next=NULL;
}
原理为:先遍历到最后一个节点,然后使得最后一个节点只想新插入的节点,新插入的节点指向空。
(3)任意位置插入---核心代码
void Add(linklist L)
{
node *p,*s;
p=L;
int i=1,m;
printf("您想将数据插入到第几个");
scanf("%d",&m);
while(p)
{
if(i==m)
break;
else
{
p=p->next;
i++;
}
}
s=(node *)malloc(sizeof(node));
printf("请输入要添加的数:");
scanf("%d",&s->data);
s->next=p->next;
p->next=s;
}
原理为:设置一个计数器i,用来确定插入的位置,如果到了需要的位置,跳出循环,若没有则继续往后走,知道找到位置。
3.单链表的删除---核心代码
void delete_linklist(linklist L)
{
int n;
node *p,*bp;
bp=L;
p=bp->next;
printf("请输入要删除的数:");
scanf("%d",&n);
while(p)
{
if(n==p->data)
{
bp->next=p->next;
break;
}
else
{
bp=bp->next;
p=p->next;
}
}
}
原理为:设置两个指针,一个是bp,另一个是p,其中bp位于p之前,若找到需要删除的数,则让bp指向p的下一下节点;没有找到的话就两个指针都往后移动。
3.单链表的修改---核心代码
void revise(linklist L)
{
int n;
node *p;
p=L->next;
printf("请输入您所想修改的数:");
scanf("%d",&n);
while(p)
{
if(p->data==n)
break;
else
p=p->next;
}
printf("请重新输入数据:");
scanf("%d",&p->data);
}
原理为:先遍历查找到需要修改的数,查找到之后退出循环,更改数据。
4.单链表的查询---源代码
为了方便体现效果,更改一下结构体中的数据类型
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node{
char name[20];
char number[20];
char phone[20];
struct node*next;
}node,*linklist;
node *creat()
{
linklist L;
node *r,*s;
char a[20];
int n;
L=r=(node *)malloc(sizeof(node));
L->next=NULL;
printf("请输入学生信息:");
while(1)
{
scanf("%s",a);
if(strcmp(a,"0")!=0)
{
s=(node *)malloc(sizeof(node));
strcpy(s->number,a);
scanf("%s",s->name);
scanf("%s",s->phone);
r->next=s;
s->next=NULL;
r=s;
}
else
break;
}
return L;
}
void find(linklist L)
{
char a[20];
node *p;
p=L->next;
int i=0;
printf("请输入您所想查找的学生姓名或者学号");
scanf("%s",a);
while(p)
{
if(strcmp(a,p->name)==0||strcmp(a,p->number)==0)
{
printf("您查找的学生信息为:\n");
printf("%s\t%s\t%s\t",p->name,p->number,p->phone);
i++;
}
p=p->next;
}
if(i==0)
printf("不好意思,没有您所想查找的学生");
}
int main()
{
linklist L;
L=creat();
find(L);
}
原理为:遍历找到需要的信息,然后输出,设置一个计数器,如果遍历结束之后计数器仍然为0,则输出没有相关的学生信息。
本篇博客先整理基本的操作,如有后续,则会继续整理。。。