单链表:同一组任意存储单元存储线性表的数据元素(逻辑地址相邻,物理地址不一定相邻)
单链表的优点:插入和删除效率高
单链表的缺点:查找慢、数据密度小,内存碎片严重
pos的位置必须在链表的合理位置,pos< 0 时返回false。对链表进行遍历,遍历完成仍没有找到pos位置。
单链表的结构体:
单链表的结构体由两部分组成,int data数据域和Node* next指针域,指针域保存其下一个节点的地址,通过地址将节点互相链接,头结点数据域为NULL,尾节点指针域为NULL。如图所示:
单链表的插入(头插、尾插、pos位置插)
for(i,q;q->next != NULL && i< pos;q = q->next ,i++)
{
;
}
if(i<pos) //已经遍历到尾节点,仍然没有找到pos位置
{
return false;
}
单链表的删除和插入是类似的,都是通过 next 域的指针来实现的,将删除位置前驱的 next 域的地址该为 删除位置的后继地址。注意:首先要用指针指向删除位置,以便于free(),防止内存泄漏。
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}Node,*List;
void InitList(List plist)
{
assert(plist != NULL);
plist->next =NULL;
}
bool Insert_head(List plist,int val)
{
Node*p = (Node*)malloc(sizeof(Node));
p->data = val;
p->next =plist->next;
plist->next =p;
return true;
}
bool Insert_tail(List plist,int val)
{
Node*p = (Node*)malloc(sizeof(Node));
Node *q = plist;
while(q ->next != NULL)
{ q = q->next ;}
p->data = val;
q->next = p;
p->next = NULL;
return true;
}
bool Insert_pos(List plist,int pos,int val)
{
if(pos < 0)
{
return false;
}
int i=1;
Node* q=plist;
for(i,q;q->next != NULL && i< pos;q = q->next ,i++)//找到pos的前一个节点
{
;
}
if(i<pos)
{
return false;
}
Node*p =( Node*)malloc(sizeof(Node));
p->data =val;
p->next = q->next ;
q->next = p;
return true;
}
Node* Search_pre(List plist,int key)
{
for(Node*q=plist;q->next != NULL;q=q->next )
{
if(q->next ->data == key) //不能为q->next,插入要先找到他的前驱,改变其前驱的next
{
return q;
}
}
return NULL;
}
bool Delete(List plist,int key)
{
Node* p= Search_pre(plist,key);
Node* q = p->next;
p->next =p->next ->next ;
free(q);
return true;
}
bool Delete_head(List plist,int *rtv)
{
if(plist->next == NULL)
{
return false;
}
Node *p = plist->next;
if(rtv != NULL)
{
*rtv = p->data;
}
plist->next = p->next;
free(p);
return true;
}
bool Delete_tail(List plist,int *rtv)
{
if(plist->next == NULL)
{
return false;
}
Node *p;//指向倒数第二个点
for(p=plist;p->next->next!=NULL;p=p->next)
{
;
}
Node *q = p->next;
if(rtv != NULL)
{
*rtv = q->data;
}
free(q);
p->next = NULL;
return true;
}
bool IsEmpty(List plist)
{
return plist->next == NULL;
}
void Destroy(List plist)
{
Node * p =plist->next;
for(p;p != NULL;p =p ->next)
{
free(p);
}
}
int GetLength(List plist)
{
int i= 0;
Node*q=plist->next;
for(q;q!=NULL;q=q->next)
{
i++;
}
return i;
}
void Show(List plist)
{
for(Node*p=plist->next ;p !=NULL;p=p->next )
{
printf("%d ",p->data);
}
printf("\n");
}
int main()
{
Node head;
InitList(&head);
printf("头插 3 2 1\n");
Insert_head(&head,3);
Show(&head);
Insert_head(&head,2);
Show(&head);
Insert_head(&head,1);
Show(&head);
printf("尾插 4 5 6 \n");
Insert_tail(&head,4);
Show(&head);
Insert_tail(&head,5);
Show(&head);
Insert_tail(&head,6);
Show(&head);
printf("在4号位置插入 100 \n");
Insert_pos(&head,4,100);
Show(&head);
printf("删除数据 100\n");
Delete(&head,100);
Show(&head);
printf("删除第一个数据\n");
Delete_head(&head,NULL);
Show(&head);
printf("删除最后一个数据\n");
Delete_tail(&head,NULL);
Show(&head);
printf("链表的长度为:");
int index = GetLength(&head);
printf("%d\n ",index);
Destroy(&head);
return 0;
}
执行结果: