链表 -- 解释头结点作用

链表中头结点会让插入与删除简化,但至于如何简化,为什么会简化可能不清楚,那我们就来实现一下删除与插入无头结点的代码。

无头结点实现插入,删除,遍历输出

#include"stdio.h"
#include"stdlib.h"

typedef struct Node {
	int data;
	struct Node* Next;
}*PNode;

int NoHead_ListInsert(PNode* List, int i, int e) {
	PNode P = *List;		int j = 1;
	if (i == 1) { //无头结点时要对插入第一个结点单独操作
		PNode l = (PNode)malloc(sizeof(struct Node));
		l->data = e;
		l->Next = P;
		*List = l; //List = &l;
	}
	else {
		while (P && j < i - 1) {
			P = P->Next;
			j++;
		}
		if (!P || i - 1 < j) {
			printf("Input i error\n");
			return 0;
		}
		PNode l = (PNode)malloc(sizeof(struct Node));
		l->data = e;
		l->Next = P->Next;
		P->Next = l;
	}
	return 1;
}

int NoHead_Delete(PNode* List, int i) {
	PNode P = *List;	int j = 1;
	if (!*List) { //无头结点,要单独判断这个链表是否为空
		printf("empty\n");
		return 0;
	}
	if (i == 1) { //无头结点,要对删除首结点单独操作
		*List = P->Next;
		free(P);
	}
	else {
		while ((P->Next) && j < i - 1) { //P->Next 是咱们要删除的结点 必须保证这个删除结点存在
			P = P->Next;
			j++;
		}
		if (i - 1 < j || !(P->Next)) {
			printf("input i error\n");
			return 0;
		}
		PNode l = P->Next;
		P->Next = l->Next;
		free(l);
	}
}

void NoHead_Print(PNode List) {
	while (List) {
		printf("%d ", List->data);
		List = List->Next;
	}
	printf("\n");
}


int main() {
	int In, De, in;
	PNode List = NULL;
	NoHead_ListInsert(&List, 0, 9);
	scanf("%d", &In);
	for (int i = 0; i < In; i++) {
		scanf("%d",&in);
		NoHead_ListInsert(&List, i + 1, in);
	}
	NoHead_Print(List);

	scanf("%d", &De);
	NoHead_Delete(&List, De);
	NoHead_Print(List);
	return 0;
}

对带头结点的链表实现

#include"stdio.h"
#include"stdlib.h"

typedef struct Node {
	int data;
	struct Node* Next;
}*PNode;

int ListInsert(PNode* List, int i, int e) {
	PNode P = *List;		int j = 0;	//如果要插入第一个结点前,P要指向头结点,所以初始化P指向头结点
	while (P && j < i - 1) { //有头结点可以统一操作
		P = P->Next;
		j++;
	}
	if (!P || i - 1 < j) {
		printf("Input i error\n");
		return 0;
	}
	PNode l = (PNode)malloc(sizeof(struct Node));
	l->data = e;
	l->Next = P->Next;
	P->Next = l;
	return 1;
}

int Delete(PNode* List, int i) {
	if (!(*List)->Next) {
		printf("List Empty\n");
		return 0;
	}
	PNode P = *List;	 int j = 0; //删除第一个结点时,P指向头结点
	while (P->Next && j < i - 1) { //P->Next 为要删除结点,必须保证存在
		P = P->Next;
		j++;
	}
	if (!(P->Next) || i - 1 < j) {
		printf("input i error\n");
		return 0;
	}
	PNode l = P->Next;
	P->Next = l->Next;
	free(l);
	return 1;
}

void Print(PNode List) {
	List = List->Next; //有头结点,要指向第一个有效结点
	while (List) {
		printf("%d ", List->data);
		List = List->Next;
	}
	printf("\n");
}

int main() {
	int In, De, in;
	PNode List = (PNode)malloc(sizeof(struct Node));
	List->Next = NULL; //注意初始化时要让最后一个结点为NULL
	ListInsert(&List, 0, 1);
	scanf("%d", &In);
	for (int i = 0; i < In; i++) {
		scanf("%d", &in);
		ListInsert(&List, i + 1, in);
	}
	Print(List);
	scanf("%d", &De);
	Delete(&List, De);
	Print(List);
}

实现代码的时候要注意:
  • 插入和删除的第i个结点时,要找到第i-1个结点,在找结点时,注意这两个操作的while循环条件不同,
    因为插入不需要管第i个结点是否为空,但删除必须要第i个结点不为空
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值