关于《链表》(单向链表的简单操作·上)

在C语言基础里,链表无疑是较为困难的一部分。但是作为具有逻辑性的东西,我们争取将复杂的问题具象化,便能使其迎刃而解。

考虑到问题的复杂性和个人能力,以下只介绍单向链表。

目录

1·创建链表

2·遍历链表

3·在链表上检索


1·创建链表

创建链表需先明确链表的结构:链表由多个数据项组成,每个数据项包括基本数据部分和指针部分;首个数据项由单独定义项指向链头。

随后我们创建链表只需在链头或链尾加入数据项即可。

而作为动态数据结构,我们需要引入动态变量。此时使用malloc函数

#include<stdio.h>
#include<malloc.h>
struct cell {
	int x;
	struct cell* next;
};//单链表节点结构体定义
struct cell* build(void) {
	struct cell* head, * tmp, * p;//定义三个数据项,head为链头,tmp待定,p为后续项
	head = tmp = p = NULL;
	int n;
	head = (struct cell*)malloc(sizeof(struct cell));
	scanf("%d", &head->x);
	tmp = head;
	tmp->next = NULL;//用tmp替代head;
	if (head->x == 0)head = NULL;
	else {
		do {
			p = (struct cell*)malloc(sizeof(struct cell));
			scanf("%d", &p->x);
			tmp->next = p;//相当于head->next=p
			tmp = p;
			tmp->next = NULL;//相当于p->next=NULL,此时p已经插入该链表
		} while (p->x != 0);
	}
	return head;//建好的链表首节点地址返回
}

接下来我们来看完整例题:

创建单链表

根据从键盘随机输入以0结束的若干非零整数,建立一个单链表;之后将此链表中保存的数字顺次输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符;若是空链表,则输出NULL。

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<malloc.h>
struct cell {
	int x;
	struct cell* next;
};//单链表节点结构体定义
struct cell* build(void) {
	struct cell* head, * tmp, * p;//定义三个数据项,head为链头,tmp待定,p为后续项
	head = tmp = p = NULL;
	int n;
	head = (struct cell*)malloc(sizeof(struct cell));
	scanf("%d", &head->x);
	tmp = head;
	tmp->next = NULL;//用tmp替代head;
	if (head->x == 0)head = NULL;
	else {
		do {
			p = (struct cell*)malloc(sizeof(struct cell));
			scanf("%d", &p->x);
			tmp->next = p;//相当于head->next=p
			tmp = p;
			tmp->next = NULL;//相当于p->next=NULL,此时p已经插入该链表
		} while (p->x != 0);
	}
	return head;//建好的链表首节点地址返回
}
void print(struct cell* head) {
	struct cell* p;
	printf("%d", head->x);
	p = head->next;
	while (p->x != 0) {
		printf(" %d", p->x);
		p = p->next;//只要该项的数据不为零,该项的指针部分就指向下一项的数据部分,以链表结构形式进行
	}//打印整个单链表
}
void release(struct cell* head) {
	struct cell* p;
	while (head != NULL) {
		p = head;
		head = p->next;
		free(p);
	}
}//释放单链表空间
int main(void) {
	struct cell* head;
	head = build();
	if (head != NULL)
		print(head);
	else
		printf("NULL");
	release(head);
}
2·遍历链表

遍历链表是指从头到尾将链表的数据全部加工一遍

p=top;
while(p!=NULL){
加工p->
p=p->next;
}

在遍历链表时,经常在加工一项数据后,当连指针前移时,另外取一个指针保留其前驱项的位置,以备后续加工使用。

p0=NULL;
p=top;
while(p!=NULL){
加工p->
p0=p;
p=p->next;
}

3·在链表上检索

检索是指在单向链表上查找关键字等于某定值给定的节点,若找到则带回相应节点的指针,否则带回NULL。

设关键字域的域名为key;欲检索的关键字值为key0,则:

p0=NULL;
p=top;
while(p!=NULL&&p->key!=key0){
p0=p;
p=p->next;
}

下面来看完整的例题来理解遍历和检索:

题目名称:求单链表中间结点

题目描述:首先根据键盘随机输入,以0结束的若干非零整数建立单链表;

然后寻找处于链表中间位置的结点,若中间结点有两个,则设定前一个为中间位置结点;

最后将从中间结点开始到链表尾各结点值输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符。

若是空链表,则输出NULL。
 

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<malloc.h>
struct cell {
	int x;
	struct cell* next;
};
struct cell* build(void) {
	struct cell* head, * tmp, * p;
	head = tmp = p = NULL;
	int n;
	head = (struct cell*)malloc(sizeof(struct cell));
	scanf("%d", &head->x);
	tmp = head;
	tmp->next = NULL;
	if (head->x == 0)head = NULL;
	else {
		do {
			p = (struct cell*)malloc(sizeof(struct cell));
			scanf("%d", &p->x);
			tmp->next = p;
			tmp = p;
			tmp->next=NULL;
		} while (p->x != 0);
	}
	return head;
}//创建单链表,首节点地址返回
struct cell* mid(struct cell* head) {
	struct cell* p0, * p;
	int n = 0, i, j = 0;
	if (head == NULL)head = NULL;
	else {
		p = head;
		while (p != NULL) {
			p = p->next;
			n = n + 1;//遍历整个单链表
		}
		j = n / 2;
		p0 = head;
		while (j != 1) {
			p0 = p0->next;
			j--;
		}
		head = p0;//找到中间节点并返回 head是单链表首节点指针
	}
	return head;//就是返回中间节点
}
void print(struct cell* head) {
	struct cell* p;
	printf("%d", head->x);
	p = head->next;
	while (p->x != 0) {
		printf(" %d", p->x);
		p = p->next;
	}
}
void release(struct cell* head) {
	struct cell* p;
	while (head != NULL) {
		p = head;
		head = p->next;
		free(p);
	}
}
int main(void) {
	struct cell* head, * half;
	head = build();
	half = mid(head);
	if (half != NULL)
		print(half);
	else
		printf("NULL");
	release(head);

}

题目名称:单链表倒数第K个结点

题目描述:    首先根据键盘随机输入,以0结束的若干非零整数建立单链表;

    然后根据输入的整数K,输出链表倒数第K个结点的值,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符;

    若不存在则输出NULL。

#include<stdio.h>
#include<malloc.h>
struct cell{
	int x;
	struct cell*next;
};
struct cell*build(void){
	struct cell*head,*tmp,*p;
	head=tmp=p=NULL;
	int n;
	head=(struct cell*)malloc(sizeof(struct cell));
	scanf("%d",&head->x);
	tmp=head;
	tmp->next=NULL;
	if(head->x==0)head=NULL;
		do{
			p=(struct cell*)malloc(sizeof(struct cell));
			scanf("%d",&p->x);
			if(p->x==0)break;
			tmp->next=p;
			tmp=p;	
		}while(p->x!=0);
	tmp->next=NULL;
	return head;
}
struct cell*back(struct cell*head,int k){
	struct cell*p,*p0;
	int n=1,i;
	if(head==NULL)head=NULL;
	else{
		while(p->next!=NULL){
			n++;
			p=p->next;
		}
		if(k>n){head=NULL;
		return head;
		}
		n=n-k;
		p0=head;
		for(i=n;i>0;i--)
		{
			p0=p0->next;
		}
		head=p0;
		p0->next=NULL;
	}
	return head;
}
void release(struct cell*head){
	struct cell*p;
	while(head!=NULL){
		p=head;
		head=p->next;
		free(p);
	}
}
int main(void){
	struct cell*head,*result;
	int k;
	head=build();
	scanf("%d",&k);
	result=back(head,k);
	if(result!=NULL)
	printf("%d",result->x);
	else
	printf("NULL");
	release(head);
}

以上简单介绍了三种链表的操作,下篇将介绍另外三种链表操作。

其主要特点皆为把握逻辑性,构造链表结构图。 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无须logic ᭄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值