1、基本组成
一个链表包含若干个结点,每一个结点由数据域和指针域组成
单链表的结点结构
typedef struct node
{
DataType data;//数据域
struct node *next;//指针域
}Node,*Link;
next指针域用来指向另一个相同结构的结点
使用Node,*Link,可以方便我们以后定义指针和结点
Node st;
//等价于struct node st;
Link p;
//等价于struct node *p;
要使p指向st结构体变量
p=&st;
之后再需要申请结点的时候就可以直接写
p=(Link)malloc(sizeof(Node));
//也可以直接写
p=(struct node*)malloc(sizeof(Node));
如果想访问结点的数据域和指针域
//数据域
p->data
//指针域
p->next
--------------------------------------------------------
有两种链表,一种是第一个节点数据部分为空。另一种是第一个节点就存放数据。
两种方式的编程是有点不同的:
第一种方式,不管怎样对链表进行增加修改和删除,head的位置都不会变化,head的值只需要传入到函数中,不需要返回。
第二种方式,如果数据插入到第一个节点,head存储的地址会发生变化。这种方式的链表在定义函数时,需要返回链表的head。
推荐使用第一种,本文也是用的是第一种
--------------------------------------------------------
2、链表的基本操作
(1)单链表的遍历
操作接口
void displayNode(Link head)
具体代码
void displayNode(Link head)
{
p=head->next;
while(p!NULL)
{
printf("%d",p->data);
p=p->next;
}
}
注意:这里不能使用p++
因为链表的存储是不连续的,p++会到指针的下一块内存,而不是链表的指针域所指向的内存
(2)求单链表元素个数
操作接口
int length(Link head);
具体代码
int length(Link head)
{
p=head->next;
count=0;
while(p!=NULL)
{
p=p->next;
count++;
}
return count;
}
(3)单链表的查找
操作接口
int queryNode(Link head,DataType x)
x是准备查找的数据,应该和数据域对应的数据类型一致
具体代码
int queryNode(Link head,DataType x)
{
p=head->next;
count=0;
while(p!=NULL)
{
if(p->data==x)
{
print(data);
return true;
}
p=p->next;
}
return false;//如果循环结束了,说明没有找到
}
(4)单链表的插入
不论插入的位置在表头、表中、表尾,代码全都适用
bool insertNode(Link head,int i,DataType x)
{
p=head;
count=0;
while(p!=NULL&&count<i-1)
{
p=p->next;
count++;
}
if(p==NULL)
{
return false;
}
else
{
node=(Link)malloc(sizeof(Node));
node->data=x;
node->next=p->next;//先和下一个结点相连
p->next=node;//再和上一个结点相连。原来中间的连接关系自动断开
return true;
}
}
(5)创建一个单链表—头插法
操作接口
Link newList(DataType a[],int n)
将待插入的结点插入到头结点的后面
最好每次创建一个结点,就马上把他的next域设置为NULL
具体代码
Link newList(DataType a[],int n)
{
//创建头结点
head=(Link)malloc(sizeof(Node));
head->next=NULL;
//创建后续结点
for(i=0;i<n;i++)
{
node=(Link)malloc(sizeof(Node));
node->data=a[i];
node->next=head->next;
head->next=node;
}
return head;
}
(6)创建一个单链表—尾插法
操作接口
Link newList(DataType a[],int n)
具体代码
Link newList(DataType a[],int n)
{
head=(Link)malloc(sizeof(Node));
head->next=NULL;
rear=head;
for(i=0;i<n;i++)
{
node=(Link)malloc(sizeof(Node));
node->data=a[i];
//node->next=NULL;
near->next=node;
rear=node;
}
rear->next=NULL;//这个语句很容易被忽略,或者在前面加一句node->next=NULL
return head;
}
(7)单链表结点的删除
操作接口
bool deleteNode(Link head,Datatype x)
具体代码
bool deleteNode(Link head,Datatype x)
{
///判断是否是空表
if(head==NULL||head->next==NULL)
{
return false;
}
p=head->next;
q=head;
while(p!=NULL)
{
if(p->data==x)
{
q->next=p->next;
free(p);
return false;
}
else
{
q=p;
p=p->next;
}
}
//如果循环结束了,说明没有找到与x相等的数据
return false;
}
(8)单链表的释放
操作接口
void clearLink(Link head)
具体代码
void clearLink(Link head)
{
while(head->next!=NULL)
{
q=head;
head=head->next;
free(p);
}
}