【数据结构】无头和有头单链表基本操作的实现与比较(C语言)

在这里插入图片描述

typedef int DataType;
typedef struct SListNode{//结点
	struct SListNode* next;
	DataType data;
}SListNode,*PListNode;

int main(){
	PListNode Phead;
}

区别:

1)尾插操作:因为如果链表为空,无头链表需要对头指针Phead进行赋值所以传参时,需要传PlistNode* 类型的数据,而头指针只需要传递PListNode类型的数据。而且无头链表尾插时更加麻烦因为如果是空链表需要改变的是phead 的值。代码如下:(BuyNewNode操作见详细代码)
无头:

void SListPushBack(PListNode* Phead, DataType data){//尾插
	assert(Phead);
	if(*Phead == NULL){
		(*Phead) = BuyNewNode(data);
	}else{
		PListNode ptr = (*Phead);
		while(ptr ->next){//找到链表最后一个元素
			ptr  = ptr ->next;
		}
		ptr ->next = BuyNewNode(data);
	}
}

有头:

void SListPushBack(PListNode Phead, DataType data){//尾插
	assert(Phead);
	while(Phead ->next){//找到最后一个元素
		Phead = Phead ->next;
	}
	Phead ->next = BuyNewNode(data);
}

(2)尾删操作 :两者的区别与尾插操作类似 :如果链表只有一个元素 无头链表需要改变(Phead)的值。而有头结点却不需要。所以有头结点更加方便 代码见(代码详情)
(3)头插 头删: 显而易见 无头结点链表需要传入 PListNode
而 有头结点需要传入 PListNode,两个操作都同样简单,只不过 无头结点链表 在Phead处做操作,有头结点,在头结点的next处做操作。
详细代码:
有头结点:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//有头单链表的实现;
typedef int DataType;
typedef struct SListNode{// 结构体SListNode用来描述:无头单链表的每个节点(节点的数据 ,下一个节点的地址);
	struct SListNode* next;
	DataType data;
}SListNode,*PListNode;
void SListInit(PListNode* list){// 链表初始化
	*list = (PListNode)malloc(sizeof(SListNode));//头结点
	(*list) ->next = NULL;
}
PListNode BuyNewNode(DataType data){//创建一个新节点 
	PListNode PNode = (PListNode)malloc(sizeof(SListNode));
	if(PNode){//申请成功
		PNode ->data = data;
		PNode ->next = NULL;
		return PNode;
	}else{
		printf("BuyNewNode failed\n");
		return NULL;
	}

}
void PrintfList(PListNode Phead){//打印链表
	assert(Phead);
	PListNode ptr = Phead ->next;
	if(ptr == NULL){
		printf("这是一个空链表");
	}else{
		while(ptr){
			printf("%d->",ptr ->data);
			ptr = ptr ->next;
		}
		printf("\n");
	}
}
void SListPushBack(PListNode Phead, DataType data){//尾插
	assert(Phead);
	while(Phead ->next){//找到最后一个元素
		Phead = Phead ->next;
	}
	Phead ->next = BuyNewNode(data);
}
void SListPopBack(PListNode Phead){//尾删
	assert(Phead);
	PListNode ptr = Phead;
	PListNode bptr = NULL;
	while(ptr ->next){
		bptr = ptr;
		ptr = ptr ->next;
	}
	if(bptr){
		bptr ->next = NULL;
		free(ptr);
	}else{//链表为空
		printf("没有元素可以删除了");
	}	
}
void SListPushFront(PListNode Phead, DataType data){// 头插
	assert(Phead);
	PListNode ptr = BuyNewNode(data);
	ptr ->next = Phead ->next;
	Phead ->next = ptr;
}
void SListPopFront(PListNode Phead){//头删
	assert(Phead);
	if(Phead ->next){
		PListNode ptr = Phead ->next;
		Phead ->next = ptr ->next;
		free(ptr);
	}else{
		printf("没有可以删除的元素");
	}
}
PListNode ListFind(PListNode Phead, DataType data){//查找data
	PListNode ptr = Phead ->next;
	while(ptr){// 如果是空链表不执行循环,返回NULL;
		if (ptr ->data == data){
			break;
		}
		ptr = ptr ->next;
	}
	return ptr;
}
bool ListInsert(PListNode Phead, PListNode pos, DataType data){//在pos位置插入 data
	if(Phead == NULL || Phead ->next == NULL){//链表为空
		return false;
	}
	PListNode ptr = Phead ->next;
	PListNode bptr = Phead;
	while(ptr){ //为空代表 没有找到pos
		if(ptr == pos){
			bptr ->next = BuyNewNode(data);
			bptr = bptr ->next;
			bptr ->next = ptr;
			break;
		}
		bptr = ptr;
		ptr = ptr ->next;
	}
	
	if(ptr == NULL){//没有找到pos 位置
		return false;
	}else{//插入成功
		return true;
	}
	
}
bool ListErase(PListNode Phead, PListNode pos){//删除pos位置的节点
	if(Phead == NULL || Phead ->next ==NULL){
		return false;
	}
	PListNode ptr = Phead ->next;
	PListNode bptr = Phead;
	while(ptr){
		if(ptr == pos){
			bptr ->next = ptr ->next;
			free(ptr);
			break;
		}else{
			bptr = ptr;
			ptr =ptr ->next;	
		}
	}
	if(ptr == NULL){
		return false;
	}else{
		return true;
	}
	
}
void ListDestroy(PListNode* Phead){//删除链表
	assert(Phead);
	if((*Phead) == NULL){
		return ;
	}
	PListNode ptr = *Phead;
	PListNode pdestory = ptr;
	while(ptr){
		ptr = ptr ->next;
		free(pdestory);
		pdestory = ptr;
	}
	*Phead = NULL;         //如果忘记*Phead 会变成野指针
}
int main(){
	PListNode Phead;
   system("pause");
}

无头结点:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//无头单链表的实现;
typedef int DataType;
typedef struct SListNode{//结点
	struct SListNode* next;
	DataType data;
}SListNode,*PListNode;
void SListInit(PListNode* Phead){// 链表初始化
	(*Phead) = NULL;
}
PListNode BuyNewNode(DataType data){//创建一个新节点 
	PListNode PNode = (PListNode)malloc(sizeof(SListNode));
	if(PNode){//申请成功
		PNode ->data = data;
		PNode ->next = NULL;
		return PNode;
	}else{
		printf("BuyNewNode failed\n");
		return NULL;
	}

}
void PrintfList(PListNode Phead){//打印链表
	if(Phead == NULL){
		printf("这是空链表");
	}else{
		PListNode ptr = Phead;
		while(ptr){
			printf("%d->",ptr ->data);
			ptr = ptr ->next;
		}
		printf("\n");
	}
}
void SListPushBack(PListNode* Phead, DataType data){//尾插
	assert(Phead);
	if(*Phead == NULL){
		(*Phead) = BuyNewNode(data);
	}else{
		PListNode ptr = (*Phead);
		while(ptr ->next){//找到链表最后一个元素
			ptr  = ptr ->next;
		}
		ptr ->next = BuyNewNode(data);
	}
}
void SListPopBack(PListNode* Phead){//尾删
	assert(Phead);
	if((*Phead) == NULL){
		printf("没有元素可以删除了");
	}else{//链表至少有一个节点
		PListNode ptr = *Phead;
		PListNode bptr = NULL;//bptr的初始值为第零个节点 
		while(ptr ->next){// 使得 ptr指向最后一个结点 bptr 为倒数第二个节点
			bptr = ptr;
			ptr = ptr ->next;
		}
		if(bptr){//链表至少有两个元素(改变 bptr ->next)
			bptr ->next =NULL;
			free(ptr);
		}else{//链表只有一个元素(改变(*Phead))
			(*Phead) = NULL;
			free(ptr);
		}
	}
}
void SListPushFront(PListNode* Phead, DataType data){// 头插
	assert(Phead);
	PListNode ptr = BuyNewNode(data);
	ptr ->next = (*Phead);
	(*Phead) = ptr;
}
void SListPopFront(PListNode* Phead){//头删
	assert(Phead);
	if(*Phead){//至少有一个元素
		PListNode ptr = (*Phead);
		(*Phead) = ptr ->next;
		free(ptr);
	}else{
		printf("没有可以删除的元素");
	}
}
PListNode ListFind(PListNode Phead, DataType data){//查找data
	PListNode ptr = Phead;
	while(ptr){// 如果是空链表不执行循环,返回NULL;
		if (ptr ->data == data){
			break;
		}
		ptr = ptr ->next;
	}
	return ptr;
}
bool ListInsert(PListNode* Phead, PListNode pos, DataType data){//在pos位置插入 data
	
	if((*Phead) == NULL || Phead == NULL){//链表为空
		return false;
	}
	PListNode ptr = *Phead;
	PListNode bptr = ptr;
	if(ptr == pos){//插入链表的第一个位置 需要改变(*Phead)
		(*Phead) = BuyNewNode(data);
		(*Phead) ->next = ptr;
	}else{
		ptr = ptr ->next;
		while(ptr){ //为空代表 没有找到pos
			if(ptr == pos){
				bptr ->next = BuyNewNode(data);
				bptr = bptr ->next;
				bptr ->next = ptr;
				break;
			}
			bptr = ptr;
			ptr = ptr ->next;
		}
	}
	if(ptr == NULL){//没有找到pos 位置
		return false;
	}else{//插入成功
		return true;
	}
}
bool ListErase(PListNode* Phead, PListNode pos){//删除pos位置的节点
	assert(Phead);
	if(*Phead == NULL){
		return false;
	}
	PListNode ptr = *Phead;
	PListNode bptr = ptr;
	if(ptr == pos){//如果是删除链表的第一个节点
		*Phead = ptr ->next;
		free(ptr);
	}else{//
		while(ptr){
			if(ptr == pos){
				bptr ->next = ptr ->next;
				free(ptr);
				break;
			}else{
				bptr = ptr;
				ptr =ptr ->next;	
			}
		}
	}
	if(ptr ==NULL){
		return false;
	}else{
		return true;
	}
}
void ListDestroy(PListNode* Phead){//删除链表
	if(Phead == NULL|| (*Phead) == NULL){
		return ;
	}
	PListNode ptr = *Phead;
	PListNode pdestory = ptr;
	while(ptr){
		ptr = ptr ->next;
		free(pdestory);
		pdestory = ptr;
	}
	*Phead = NULL;         //如果忘记*Phead 会变成野指针
}
int main(){
	PListNode Phead;
	system("pause");

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是单链表操作实现getelem的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义单链表结构体 typedef struct node { int data; struct node* next; } Node; // 创建单链表 Node* createList(int arr[], int n) { Node* head = NULL; Node* tail = NULL; for (int i = 0; i < n; i++) { Node* node = (Node*)malloc(sizeof(Node)); node->data = arr[i]; node->next = NULL; if (head == NULL) { head = node; tail = node; } else { tail->next = node; tail = node; } } return head; } // 获取单链表指定位置的元素值 int getElem(Node* head, int position) { int i = 0; Node* curr = head; while (curr != NULL && i < position) { curr = curr->next; i++; } if (curr == NULL) { printf("Error: position out of range.\n"); return -1; } else { return curr->data; } } int main() { int arr[] = {1, 2, 3, 4, 5}; int n = sizeof(arr) / sizeof(arr[0]); Node* head = createList(arr, n); printf("The list: "); Node* curr = head; while (curr != NULL) { printf("%d ", curr->data); curr = curr->next; } printf("\n"); printf("The element at position 2 is %d.\n", getElem(head, 2)); printf("The element at position 5 is %d.\n", getElem(head, 5)); return 0; } ``` 输出结果为: ``` The list: 1 2 3 4 5 The element at position 2 is 3. Error: position out of range. The element at position 5 is -1. ``` 以上代码实现单链表基本操作之一:获取指定位置的元素值。在 `getElem` 函数中,我们使用了一个循环遍历链表,依次访问每个节点,直到找到目标位置对应的节点,然后返回该节点的数据值。如果目标位置超出了链表的范围,我们输出错误信息并返回 -1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值