在C语言中,链表是我们不可避免的难题,如何解决成为了一个问题,首先我们需要先认识链表…
链表的定义
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
简单来说,链表就是动态分配的存储结构,由多个结点构成,各节点包括:1.数据域 2.指针域。从链表的实现方式一般分为单链表、双链表、循环链表。
链表与数组的区别
从链表与数组的功能来看,链表是一个功能更强大的数组,那么两者有什么区别呢?
1.内存分配 数组静态分配内存,链表动态分配内存;
2.内存存储 数组在内存中连续,链表不连续;
3.定位方式 数组利用下标定位,时间复杂度为O(1),链表需要从头遍历,时间复杂度O(n);
4.插入删除方式 数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
5.内存利用 申请数组前需要规定大小,可能会浪费空间,链表的空间利用率较高
数组的优点
- 随机访问性强(通过下标进行快速定位)
- 查找速度快
数组的缺点
- 插入和删除效率低(插入和删除需要移动数据)
- 可能浪费内存(因为是连续的,所以每次申请数组之前必须规定数组的大小,如果大小不合理,则可能会浪费内存)
- 内存空间要求高,必须有足够的连续内存空间
- 数组大小固定,不能动态拓展
链表的优点
- 插入删除速度快(通过改变指针的指向可以方便的增加删除元素)
- 内存利用率高,不会浪费内存(可以使用内存中细小的不连续空间(大于node节点的大小),并且在需要空间的时候才创建空间,不需要时可以释放)
- 大小没有固定,拓展很灵活。
链表的缺点
- 不能随机查找,必须从第一个开始遍历,查找效率低!
单链表
单链表的声明
strcut node
{
int data;//数据
strcut node *pnext;//指针指向下一结点
};
int count;//记录链表长度(全局变量)
单链表的建立
struct node*create()
{
strcut node *phead=NULL;
struct node *pnew,*pend;
pnew=pend=(struct node *)malloc(sizeof(struct node));
scanf("%d",&pnew->data);
while(pnew->data>0)
{
if(count==1)
{
pnew->next=phead;
pend=pnew;
phead=pnew;
}
else
{
pnew->next=NULL;
pend->next=pnew;
pend=pnew;
}
pnew=(struct node *)malloc(sizeof(struct node));
scanf("%d",&pnew->data);
}
free(pnew);
return phead;
}
单链表的插入(头插法)
struct node* insert(struct node *phead)
{
struct node *pnew;
pnew=(struct node*)malloc(sizeof(struct node));
scanf("%d",&pnew->data);
pnew->next=phead;
phead=pnew;
count++;
return phead;
}
单链表的插入(尾插法)
struct node* insert(struct node *phead)
{
struct *pnew,*pend;
pend=phead;
while(pend&&pend->next!=NULL)
pend=pend->next;
pnew=(struct node*)malloc(sizeof(struct node));
scanf("%d",&pnew->data);
pend->next=pnew;
pnew->next=NULL;
count++;
return phead;
}
单链表在某一位置处插入(比如在数据flag的位置后插入)
struct node* insert(struct node *phead,int flag)
{
struct *pnew,*ptemp;
ptemp=phead;
while(ptemp&&ptemp->data!=flag)
ptemp=ptemp->next;
pnew=(struct node*)malloc(sizeof(struct node));
scanf("%d",&pnew->data);
pnew->next=ptemp->next;
ptemp->next=pnew;
count++;
return phead;
}
单链表的删除
struct node* del(struct node *phead,int index)//**index**是要删除的结点数
{
int i;
struct node *ppre,*ptemp;
ppre=ptemp=phead;
for(i=0;i<index;i++)
{
ppre=ptemp;
ptemp=ptemp->next;
}//从开始到要删除的节点依次遍历,找到要删除的结点前的结点;
ppre->next=ptemp->next;//将要删除的结点前的结点的指针,指向要删除的结点指向的结点
free(ptemp);
return phead;
}
单链表的查找
void search(struct node *phead)
{
int search_data,flag=0;
struct node *pnew;
pnew=phead;
printf("请输入要查找的数据:\n");
scanf("%d",&search_data);
while(pnew!=NULL&&pnew->next!=NULL)
{
if(pnew->data==search_data)
{
printf("Right\n");
flag=1;
break;
}
pnew=pnew->next;
}
if(flag==0)
printf("Wrong\n");
}
单链表的修改
void modify(struct node *phead)
{
int modify_data1,modify_data2,flag=0;
struct node *pnew;
pnew=phead;
printf("请输入要修改的原数据:\n");
scanf("%d",&modify_data1);
while(pnew!=NULL&&pnew->next!=NULL)
{
if(pnew->data==modify_data1)
{
printf("请输入修改后的新数据:\n");
scanf("%d",&modify_data2);
pnew->data=modify_data2;
}
pnew=pnew->next;
}
}
可以说单链表的修改与查找是很像的,修改是在查找的基础上完成的
单链表的显示
void print(struct node *phead)
{
struct node *pnew;
pnew=phead;
while(pnew!=NULL&&pnew->next!=NULL)
{
printf("%d ",pnew->data);
pnew=pnew->next;
}
}
单链表的排序(交换数据域)
struct node* sort(struct node *phead)
{
struct node *pnew,*pend;
for(pnew=phead;pnew!=NULL;pnew=pnew->next)
{
for(pend=pnew->next;pend!=NULL;pend=pend->next)
if(pend->data<pnew->data)
{
int temp;
temp=pend->data;
pend->data=pnew->data;
pnew->data=temp;
}
}
return phead;
}
主函数
#include <stdio.h>
int main()
{
struct node *phead;
phead=(struct node*)malloc(struct node);
int index;
scanf("%d",&index);
phead=create();
phead=insert(phead);
phead=del(phead,index);
modify(phead);
search(phead);
sort(phead);
print(phead);
return 0;
}