数据结构——c实现链表增删查改

在数据结构中,顺序表和链表的增删查改是基础的知识,下边是我学习链表的一些心得。

链表的增删查改。(后附完整代码实现)

尾插:(思路:先创建一个新的结点,让链表遍历到最后一个结点,让最后一个节点的next指向下一个newNode即可)

代码实现:

//尾插一个元素到链表中
void LinkListPushBack(LinkNode** head,LinkType value){
	if(head == NULL){
		return;
	}
	if(*head == NULL){
		*head = CreatNewNode(value);
		return;
	}
	LinkNode *phead = *head;
	while(phead->next){
		phead = phead->next;
	}
	phead->next = CreatNewNode(value);
	return;
}

尾删一个元素:

    思路:定义两个指针,使其遍历链表,同时++,当cur->next指向为空的时候,停止,销毁cur指向的节点。


代码实现:

void LinkListPopBack(LinkNode** head){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		return;
		//空链表
	}
	if((*head)->next == NULL){
		DestoryNode(*head);
		*head == NULL;
		return;
	}
	LinkNode* pre = NULL;
	LinkNode* cur = *head;
	while(cur->next != NULL){
		pre = cur;
		cur = cur->next;
	}
	pre->next = NULL;
	DestoryNode(cur);
	return;
}

头插和头删:

头插思维:创建一个新的节点,使其next指向头结点,再将NewNode成为头结点。

头删思维:将头结点变为头结点的下一个节点,销毁之前的头结点即可


代码实现:

//头插一个元素
void LinkListPushHead(LinkNode** head,LinkType value){
	if(head ==NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = *head;
	*head = NewNode;
	return;
}

//头删一个元素
void LinkListPopHead(LinkNode** head){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		//空链表
		return;
	}
	LinkNode* cur = *head;
	*head = (*head)->next;
	DestoryNode(cur);
	return;
}

在元素之后插入元素:

与尾插的思维相差不多,但是不用遍历,直接使其创建的节点指向就行。但是需要注意的是,需要先让新结点指向下一个节点,不然pos的下一个知不道正确的地址。


代码实现:

//在下标为pos后插入值
void LinkListInsert(LinkNode* pos,LinkType value){
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	return;
}

在元素之前插入元素:

思路:这个实现起来还是挺有意思的,要实现一种偷梁换柱的思维。先实现元素之后的插入,然后进行值交换,即可得到结果。


代码实现:


//在下标为pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		return;
		//空链表
	}
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	NewNode->data = pos->data;
	pos->data = value;
	return;
}

后边的查找和删除就直接写代码了:

//实现删除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		//空指针
		return;
	}
	LinkNode* cur = *head;
	LinkNode* pos = LinkListFind(*head,value);
	for(; cur != NULL; cur = cur->next){
		break;
	}
	if(cur == NULL){
		return;
	}
	cur->next = pos->next;
	DestoryNode(pos);
}

//删除一个元素值出现的所有情况
void LinkListDelAll(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(head == NULL){
		return;
	}
	LinkNode* cur = *head;
	while(cur != NULL){
		while(cur->data == value){
			cur = cur->next;
		}
		*head = cur;
		LinkNode* pos = *head;
		cur = cur->next;
		while(cur != NULL){
			if(cur->data !=value){
				pos->next = cur;
				pos = pos->next;
			}
			cur = cur->next;
		}
		pos->next == NULL;
		pos = pos->next;
		DestoryNode(pos);
	}
	return;
}

//查找一个元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
	if(head == NULL){
		return NULL;
	}
	LinkNode* cur = head;
	for(;cur != NULL;cur=cur->next){
		if(cur->data == value){
			return cur;
		}
	}
	return NULL;
}

实现完整代码;

LinkList.h:

#pragma once
#include<stdio.h>

typedef char LinkType;     //重定义类型

typedef struct LinkNode{       //定义结构体
	LinkType data;         //数据域
	struct LinkNode* next;     //指针域
}LinkNode;

void LinkListInit(LinkNode** head);    //初始化链表

void PrintChar(LinkNode* head,char* msg);    //打印链表

void DestoryNode(LinkNode* node);        //实现销毁一个结点

void LinkListDestory(LinkNode** head);      //实现删除一个结点

LinkNode* CrearNewNode(LinkType value);      //创建一个新结点

void LinkListPushBack(LinkNode** head,LinkType value);    //尾插一个元素到链表中

void LinkListPosBack(LinkNode** head);        //尾删一个元素

void LinkListPushHead(LinkNode** head,LinkType value);     //头插一个元素

void LinkListPopHead(LinkNode** head);     //头删一个元素

LinkNode* LinkListFind(LinkNode* head,LinkType value);      //查找元素值的下标

void LinkListInsert(LinkNode* pos,LinkType value);        //在Pos下标后插入值

void LinkedListInsertBef(LinkNode** head,LinkNode* pos,LinkType value);     //在pos>    下标前插入元素

void LiskListDelVal(LinkNode** head,LinkType value);       //删除指定元素

void LiskListDelAll(LinkNode** head,LinkType value);       //删除所有的a元素

size_t LinkListSize(LinkNode* head);                       //元素个数

代码实现:LinkList.c

#include "LinkedList.h"
#include<stdlib.h>

//初始化链表
void LinkListInit(LinkNode** head){
	*head = NULL;
}

//实现创建一个新的结点
LinkNode* CreatNewNode(LinkType value){     
	LinkNode* NewNode = (LinkNode*)malloc(sizeof(LinkNode));
	NewNode->data = value;
	NewNode->next = NULL;
	return NewNode;
}

//打印代码函数
void PrintChar(LinkNode* head,char* msg){
	if(head == NULL){
		return;
	}
	printf("%s\n\n",msg);
	while(head){
		printf("[%c]",head->data);
		head=head->next;
	}
	printf("\n\n");
}

//实现销毁一个结点
void DestoryNode(LinkNode* node){        
	if(node == NULL){
		return;
	}
	free(node);
}

//实现删除节点
void LinkListDestory(LinkNode** head){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		//空结点
		return;
	}
	LinkNode* cur = *head;
	while(*head !=NULL){
		cur = (*head)->next;
		DestoryNode(*head);
		*head = cur;
	}
	return;
}




//尾插一个元素到链表中
void LinkListPushBack(LinkNode** head,LinkType value){
	if(head == NULL){
		return;
	}
	if(*head == NULL){
		*head = CreatNewNode(value);
		return;
	}
	LinkNode *phead = *head;
	while(phead->next){
		phead = phead->next;
	}
	phead->next = CreatNewNode(value);
	return;
}


//尾删一个元素
void LinkListPopBack(LinkNode** head){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		return;
		//空链表
	}
	if((*head)->next == NULL){
		DestoryNode(*head);
		*head == NULL;
		return;
	}
	LinkNode* pre = NULL;
	LinkNode* cur = *head;
	while(cur->next != NULL){
		pre = cur;
		cur = cur->next;
	}
	pre->next = NULL;
	DestoryNode(cur);
	return;
}

//头插一个元素
void LinkListPushHead(LinkNode** head,LinkType value){
	if(head ==NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = *head;
	*head = NewNode;
	return;
}

//头删一个元素
void LinkListPopHead(LinkNode** head){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		//空链表
		return;
	}
	LinkNode* cur = *head;
	*head = (*head)->next;
	DestoryNode(cur);
	return;
}

//在下标为pos后插入值
void LinkListInsert(LinkNode* pos,LinkType value){
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	return;
}

//在下标为pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		return;
		//空链表
	}
	if(pos == NULL){
		return;
	}
	LinkNode* NewNode = CreatNewNode(value);
	NewNode->next = pos->next;
	pos->next = NewNode;
	NewNode->data = pos->data;
	pos->data = value;
	return;
}

//查找一个元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
	if(head == NULL){
		return NULL;
	}
	LinkNode* cur = head;
	for(;cur != NULL;cur=cur->next){
		if(cur->data == value){
			return cur;
		}
	}
	return NULL;
}

//实现删除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(*head == NULL){
		//空指针
		return;
	}
	LinkNode* cur = *head;
	LinkNode* pos = LinkListFind(*head,value);
	for(; cur != NULL; cur = cur->next){
		break;
	}
	if(cur == NULL){
		return;
	}
	cur->next = pos->next;
	DestoryNode(pos);
}

//删除一个元素值出现的所有情况
void LinkListDelAll(LinkNode** head,LinkType value){
	if(head == NULL){
		//非法输入
		return;
	}
	if(head == NULL){
		return;
	}
	LinkNode* cur = *head;
	while(cur != NULL){
		while(cur->data == value){
			cur = cur->next;
		}
		*head = cur;
		LinkNode* pos = *head;
		cur = cur->next;
		while(cur != NULL){
			if(cur->data !=value){
				pos->next = cur;
				pos = pos->next;
			}
			cur = cur->next;
		}
		pos->next == NULL;
		pos = pos->next;
		DestoryNode(pos);
	}
	return;
}

//实现元素个数
size_t LinkListSize(LinkNode* head){
	if(head == NULL){
		return 0;
	}
	LinkNode* pos = head;
	size_t count = 0;
	while(pos != NULL){
		++count;
		pos = pos->next;
	}
	return count;
}



//********************测试代码************************************//


#define FUNCTION printf("--------------------%s-------------------\n",__FUNCTION__);

//初始化
void TestInit(){
	LinkNode* head;
	LinkListInit(&head);
}

//测试尾插一个元素
void TestLinkListPushBack(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四个元素**************");
}

//测试尾删元素
void TestLinkListPopBack(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四个元素**************");
	LinkListPopBack(&head);
	PrintChar(head,"****************尾删一个元素**************");
}

//测试头插一个元素
void TestLinkListPushHead(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************头插四个元素**************");
}

//测试头删一个元素
void TestLinkListPopHead(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************头插四个元素**************");
	LinkListPopHead(&head);
	PrintChar(head,"****************头删一个元素**************");
}
//测试在pos下标后插入值
void TestLinkListInsert(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushHead(&head,'d');
	LinkListPushHead(&head,'c');
	LinkListPushHead(&head,'b');
	LinkListPushHead(&head,'a');
	PrintChar(head,"****************头插四个元素**************");
	LinkNode* pos = head->next;
	LinkListInsert(pos,'d');
	PrintChar(head,"************插入一个元素******************");
}
	
	
//测试查找一个元素
void TestLinkListFind(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四个元素**************");
	LinkNode* pos = LinkListFind(head,'a');
	printf("pos except %p,actual %p\n",head->next,pos);
	PrintChar(head,"****************查找元素**************");

}
	
//测试在pos下标前插入一个元素
void TestLinkListInsertBef(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四个元素**************");
	LinkNode* pos = LinkListFind(head,'d');
	LinkListInsertBef(&head,pos,'x');
	PrintChar(head,"********************在d之前插入**********");
}

//测试在pos下标前插入一个元素
void TestLinkListDelVal(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'d');
	PrintChar(head,"****************尾插四个元素**************");
	LinkListDelVal(&head,'b');
	PrintChar(head,"****************删除元素c*****************");
}

//测试删除所有的a元素
void TestLinkListDelAll(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'c');
	PrintChar(head,"****************尾插七个元素**************");
	LinkListDelAll(&head,'a');
	PrintChar(head,"****************删除所有的a元素**************");
}

//测试代码
void TestSize(){
	LinkNode* head;
	FUNCTION;
	LinkListInit(&head);
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'a');
	LinkListPushBack(&head,'b');
	LinkListPushBack(&head,'c');
	LinkListPushBack(&head,'c');
	size_t ret = LinkListSize(head);
	printf("szie = %d\n",ret);
}

//主函数
int main(){
	TestInit();
	TestLinkListPushBack();
	TestLinkListPopBack();
	TestLinkListPushHead();
	TestLinkListPopHead();
	TestLinkListInsert();
	TestLinkListFind();
	TestLinkListInsertBef();
	TestLinkListDelVal();
	TestLinkListDelAll();
	TestSize();
	return 0;
}

运行部分截图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值