单链表的建立及操作
一、逆序建表
1.单链表的建立
单链表的实质是一个结点的序列,建立单链表实质上就是逐个生成每一个结点,并把结点插入链表的过程。
单链表的建立是一个结点插入的过程,只不过需要插入的不是一个结点,而是多个结点而已。
多个结点的插入方式是相同的,因此可以借助循环过程来实现。
2.逆序建链表
①首先建立一个只包含头结点的空链表。
需要执行的操作是:
head=(struct node*)malloc(sizeof(struct node));
②在空链表头结点之后插入第一个结点。
需要执行的操作:
p=(struct node*)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=head->next;
head->next=p;
③在上面链表的头结点之后插入第二个结点。
需要执行的操作:
p=(struct node*)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=head->next;
head->next=p;
④按照同样的方法一次插入第三个、第四个…第n个结点。
需要执行的操作:
p=(struct node*)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=head->next;
head->next=p;
按照上述步骤,有如下:
struct node *creat1(int n)
{
struct node *head,*p;
int i;
head=(struct node *)malloc(sizeof(struct node));
head->next=NULL;
for(i=1;i<=n;i++)
{
p=(struct node *)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=head->next;
head->next=p;
}
return (head);
};
二、顺序建表
1.顺序建链表也是一个结点逐个插入的过程,只不过逆序建链表每次都是在头结点之后插入,而顺序建链表是在最后一个结点之后插入罢了。
2.链表中的最后一个结点常被称为尾结点。
3.为了更好地标记插入位置,设置一个专门的指针变量来保存尾结点地址,该指针变量称为尾指针。
当链表顺序插入结点后尾指针的值要随之修改,以指向新的尾结点。
①首先建立一个只包含头结点的空链表,此时头指针、尾指针均指向头结点。
需要的操作:
head=(struct node *)malloc(sizeof(struct node));
head->next=NULL;
tail=head;
②在空链表头结点之后插入第一个结点。
需要执行的操作:
p=(struct node *)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=NULL;
tail->next=p;
tail=p;
③按照同样的操作,可以在上面的链表的尾结点之后插入第二个结点。
p=(struct node *)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=NULL
tail->next=p;
tail=p;
按照这样的方式还可以继续插入后面每一个结点,而且每个结点的插入要执行的操作是完全一样的。
按照上述步骤,有如下:
struct node *creat2(int n)
{
struct node *head,*tail,*p;
int i;
head=(struct node *)malloc(sizeof(struct node));
head->next=NULL;
tail=head;
for(i=1;i<=n;i++)
{
p=(struct node *)malloc(sizeof(struct node));
scanf("%d",&p->data);
p->next=NULL;
tail->next=p;
tail=p;
}
return (head);
};
小结:
1.顺序建表是将新结点插入到尾结点的建表方法。
2.无论是哪种方式建立的单链表,特点是一样的。尾结点的指针域为NULL。
三、单链表的查找
数组由于是地址连续的空间存放元素,利用数组名+下标的方式可以实现对元素的随机查找。
单链表是用地址离散的空间存放元素的,不能直接知道每一个结点的存放地址,只能从头指针所指结点开始逐个往后才能找到要访问的结点,因此也称单链表是一种“顺序存取”的结构。
单链表的查找过程:
1.设置头指针与游动指针;其中头指针提供了链表中查找的起始位置。
2.游动指针从该起始位置开始逐个往后“游走”,直到找到要找的结点或者到了链表结束停止查找。
小结:
1.顺序查找
2.判断访问所有结点的条件是p==null;
四、单链表的插入
单链表与数组的不同之处还体现在单链表是一个动态存储的结构,可以在需要时再分配空间,用完后马上释放空间。
与数组插入删除需要移动元素不同,都不需要做元素的移动,实现过程非常简洁。
1.插入位置的三种情况:头结点的后面、链表中间、尾结点的后面。
2.要在链表插入一个元素时,如果已经确定了该元素的1插入位置,需要做的有两点:
(1)把为要插入的元素分配空间,生成一个新结点;
(2)是通过指针域的修改,把新结点插入到链表中。
①开辟新结点
②修改指针域
五、单链表结点的删除
与结点的插入类似,结点的删除也不需要作元素的移动,而只需要作指针的修改即可。
作为动态分配的存储结构,当链表的结点不再需要时,可以在删除结点时将其所占的内存空间释放。
1.要删除结点,应该如何去调整指针?
①首先要找到被删除结点的前一个结点(前驱结点)
②然后再对这前一个结点实施指针的修改操作。
删除该结点是通过其前驱结点的指针域来实现的,因此,在删除之前首先应找到被删结点的前驱结点。
2.被删除的结点有可能在哪个位置?
删除该结点是通过其前驱结点的指针域来实现的,因此,在删除之前首先应找到被删结点的前驱结点。
小结:
删除结点无需移动其他结点,只需要调整指针。
需要找到被删结点的前驱结点。