【数据结构】链表的增删改查| 组件化封装

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
🔥专栏汇总:全部文章专栏汇总 🔥
给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ



本文基于链表的基础知识之上, 将常用的链表函数功能 汇总

【c语言实现】链表基础知识

在这里插入图片描述


一、组件化封装的意义

组件化封装就是将平时常用的一些函数,根据经验归纳总结到一个文件中,便于以后再次使用。

1.提升代码复用性:组件化封装可以将一些通用的、经常使用的功能和界面进行封装,以供其他模块或项目复用,减少重复工作,提升开发效率。

2.降低维护成本:组件化封装使代码模块化,一旦封装好了某一个功能或界面,就可以在不同的项目中复用。这样可以减少代码冗余,降低维护成本。

3.提高代码可读性和可维护性:不同的组件之间有着清晰的接口和依赖关系,代码的逻辑更加清晰,易于维护和扩展。

4.促进团队合作。

二、链表的增删改查 组件化封装:

总代码文件:

头文件linkedlist.h:

#pragma once
#include <stdio.h>
#include <stdlib.h>

/*节点结构体*/
typedef struct node 
{
	struct node *prev;
	void * data;
	struct node *next;
} Node , * PNode;

/*链表结构体*/
typedef struct 
{
	PNode header;
	PNode ender;
	int size;
	PNode nextNode;//迭代器的下一个节点

}LinkedList ,* PLinkedList ;

/*创建链表*/
PLinkedList createLinkedList();
/*创建节点*/
PNode createNode(  void * data);

 /*增加新的节点*/
void add(PLinkedList  list ,  void * data);
 
/*在某节点的位置上插入新节点*/
void insert(PLinkedList  list ,int index,  void * data);

/*删除 指定 下标的节点*/
void* removeIndex(PLinkedList  list ,int index);

/*删除等于参数的首个节点*/
void removeData(PLinkedList  list ,  void* data);

/*某下标对应的 节点*/
void* get(PLinkedList  list ,int index);
/*找到节点*/
PNode findNode(PLinkedList  list ,int index);

/*某下标对应的 节点数据进行更新 */
void set(PLinkedList  list ,int index,  void* newdata);

/*某数据对应的下标*/
int indexOf(PLinkedList  list ,  void* data);

/*节点数量*/
int size(PLinkedList  list );

/*清空链表*/
void clear(PLinkedList  list );


 /*迭代器*/
//产生新的迭代器
void iterator(PLinkedList list);
//是否有下一个节点
int hasNext(PLinkedList list);
//取得下一个节点数据
void* next(PLinkedList list);



/*实现栈stack的功能:LIFO:last in first out */

/* 入栈*/
void push(PLinkedList  list ,  void* data);

/*出栈*/
void* pop(PLinkedList  list );

/*实现队列queue的功能:FIFO:first in first out */
void addFirst(PLinkedList  list ,  void* data);
void addLast(PLinkedList  list ,  void* data);
void* removeFirst(PLinkedList  list);
void* removeLast(PLinkedList  list);

源文件LinkedList.cpp :

#include "linkedlist.h"

PLinkedList createLinkedList()
{
	PLinkedList newList =(PLinkedList) malloc(sizeof(LinkedList));
	newList->header = NULL;
	newList->ender = NULL;
	newList->size = 0;
	newList->nextNode = NULL;
	return newList;
}

PNode createNode(void* data)
{
	PNode newNode = (PNode)malloc( sizeof(Node));
	newNode->prev = NULL;
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

void add(PLinkedList list, void* data)
{
	PNode newNode =createNode(data);
	if (list->size==0)//空链表
	{
		list->header = newNode;
		list->ender = newNode;
	}
	else
	{
		list->ender->next = newNode;
		newNode->prev = list->ender;
		list->ender = newNode;
	}
	list->size++;
}

void insert(PLinkedList list, int index, void* data)
{
	if ( index>= list->size )//追加到尾部 
	{
		add(list, data);
		return;
	}
	 
	PNode newNode = createNode(data);
	//插入到头部
	if (index <=0 )
	{
		newNode->next = list->header;
		list->header->prev = newNode;
		list->header = newNode;
	}
	else
	{
		//1 理想的中间插入
		PNode p = findNode(list, index);
		PNode q = p->prev;

		newNode->next = p;
		p->prev = newNode;

		newNode->prev = q;
		q->next = newNode;
	}
	list->size++;
}

void* removeIndex(PLinkedList list, int index)
{
	PNode p = NULL;//指向被删除的节点
	if (list->size==1)//唯一节点
	{
		p = list->header;
		list->header = list->ender = NULL;
	}
	else if ( index<=0 )
	{
		p = list->header;
		list->header = p->next;
		list->header->prev = NULL;
	}
	else if ( index>=list->size-1)
	{
		p = list->ender;
		list->ender = p->prev;
		list->ender->next = NULL;
	}
	else
	{
		//理想的中间删除
		p = findNode(list, index);
		PNode q = p->prev;
		PNode m = p->next;
		q->next = m;
		m->prev = q;
	}
	if (p!=NULL)
	{
		void* tdata = p->data;
		free(p);
		list->size--;
		return tdata;
	}
	return NULL;
}

void removeData(PLinkedList list, void* data)
{
	int i=indexOf(list, data);
	if (i>=0)
	{
		removeIndex(list, i);
	}
}

void* get(PLinkedList list, int index)
{
	PNode p = findNode(list, index);
	if (p)
	{
		return p->data;
	}
	return NULL;
}

PNode findNode(PLinkedList list, int index)
{
	PNode p = list->header;
	for (int i=0 ;i<index ;i++ )
	{
		p = p->next;
	}
	return p;
}

void set(PLinkedList list, int index, void* newdata)
{
	PNode p=findNode(list, index);
	if (p)
	{
		p->data = newdata;
	}
}

int indexOf(PLinkedList list, void* data)
{
	int i = 0;
	iterator(list);
	while ( hasNext(list))
	{
		if ( next(list)== data)
		{
			return i;
		}
		i++;
	}
	return -1;
}

int size(PLinkedList list)
{
	return list->size;
}

void clear(PLinkedList list)
{
	PNode p = list->header;
	PNode q;
	while (p)
	{
		q = p;
		p = p->next;
		free(q);
	}
	list->header = NULL;
	list->ender = NULL;
	list->size = 0;
}

void iterator(PLinkedList list)
{
	list->nextNode = list->header;
}

int hasNext(PLinkedList list)
{
	return list->nextNode!=NULL;
}

void* next(PLinkedList list)
{
	void* data = list->nextNode->data;
	list->nextNode = list->nextNode->next;//为下一次做准备
	return data;
}

void push(PLinkedList list, void* data)
{
	add(list, data);
}

void* pop(PLinkedList list)
{

	return removeIndex(list,list->size-1);
}

void addFirst(PLinkedList list, void* data)
{
	insert(list, 0, data);
}

void addLast(PLinkedList list, void* data)
{
	add(list, data);
}

void* removeFirst(PLinkedList list)
{
	return removeIndex(list,0);
}

void* removeLast(PLinkedList list)
{
	return removeIndex(list,list->size-1);
}

用例测试文件useLinkedList.cpp :

对LinkedList中实现功能的函数进行用例测试

#include "linkedlist.h"
#include "string.h"
/*数据域*/
typedef struct  
{
	int data;

} Data,*PData;
/*创建数据域*/
PData createData(int d);

int main()
{
	PLinkedList list = createLinkedList();
	add(list, "张三");//0
	add(list, "李四");//1
	add(list, "旺旺");//2
	add(list, "天喜");//3 
	add(list, "椰子");//4
	set(list, 1, "路飞");

	printf("下标:%d\n", indexOf(list,"天喜"));
	//removeData(list, "李四");
	//insert(list, 3, "咖啡");
	//insert(list, 8, "末尾");
	//insert(list, 0, "开头");
	/*printf("%s\n",(const char*) removeIndex(list, 2));
	printf("%s\n", (const char*)removeIndex(list, 4));
	printf("%s\n", (const char*)removeIndex(list, 0));*/
	 
	//下标遍历
	//for (int i=0 ;i<size(list); i++)//
	//{
	//	const char * str =  (const char*)get(list, i);
	//	printf("%s\n",str);
	//}

	/*PNode p = list->header;
	while (p)
	{
		printf("%s\n", (const char*)p->data);
		p=p->next;
	}*/
	//iterator(list);
	//while ( hasNext(list) )
	//{
	//	printf("%s\n", (const char*) next(list));
	//}
	
	释放链表
	//clear(list);
	//free(list);
	//list = NULL;

	//PLinkedList list1 = createLinkedList();
	//PLinkedList list2 = createLinkedList();
	//PLinkedList stack = createLinkedList();
	//push(stack, "aa");
	//push(stack, "bb");
	//push(stack, "cc");
	//push(stack, "dd");
 //
	//printf("%s\n", (const char*)pop(stack));//dd
	//printf("%s\n", (const char*)pop(stack));
	//printf("%s\n", (const char*)pop(stack));
	//printf("%s\n", (const char*)pop(stack));
	//PLinkedList queue = createLinkedList();
	//addFirst(queue, "aa");
	//addFirst(queue, "bb");
	//addFirst(queue, "cc");
	//addFirst(queue, "dd");

	//printf("%s\n", (const char*)removeLast(queue)); 
	//printf("%s\n", (const char*)removeLast(queue));
	//printf("%s\n", (const char*)removeLast(queue));
	//printf("%s\n", (const char*)removeLast(queue));

	return 0;
}
 
PData createData(int d)
{
	PData pd = (PData)malloc(sizeof( Data));
	pd->data= d;
	return pd;
}

就是在同一项目下建立一个测试用的文件,输入函数的定义进行功能测试:

如果达到了预期效果,该函数就是编写成功

在这里插入图片描述

三、交换、打乱、排序、查找等功能

总代码文件:

头文件collections.h

#pragma once
#include <time.h>
#include "linkedlist.h"
/*定义一个可指向比较函数的函数指针
  此函数用于用户自定义结构数据的比较
  比较结果分为 
  大于0 等于0 和小于0来表达两个参数的大小关系
*/
typedef  int(*Compare)(  void*,  void *);
/*将链表2 追加到链表1的后面*/
void  addAll__(PLinkedList list1, PLinkedList list2);
/*返回最大数据域*/
void*  max__(PLinkedList list,Compare fun);
/*返回最小数据域*/
void*  min__(PLinkedList list,Compare fun);
/*交换 两个下标对应的数据域*/
void swap__(PLinkedList list, int i, int j);
/*对链表 按 Compare比较规则 进行排序 */
void sort__(PLinkedList list,Compare fun );
/*使用折半查找思路 查询某key数据的下标*/
int binarySearch__(PLinkedList list,   void * key, Compare fun);
/*打乱链表的顺序*/
void shuffle__(PLinkedList list);
/*对链表成员进行首尾倒置*/
void  reverse__(PLinkedList list);
/*把符合fun比较规则的数据域 替换成新的数据域*/
void replaceAll__(PLinkedList list,  void *oldVal,   void *newVal, Compare fun  );
	 

源文件Collection.cpp :

#include "collections.h"
#include "linkedlist.h"
void addAll__(PLinkedList list1, PLinkedList list2)
{
	//方案1
	/*list1->ender->next = list2->header;
	list2->header->prev = list1->ender;
	list1->size += list2->size;*/
	//方案2
	iterator(list2);
	while ( hasNext(list2))
	{
		add(list1, next(list2));
	}
}

void* max__(PLinkedList list, Compare fun)
{ 
	void* max_value = list->header->data;
	PNode p = list->header->next;
	while (p!=NULL)
	{
		if ( fun(max_value, p->data) <0)
		{
			max_value = p->data;
		}
		p = p->next;
	}

	return max_value;
}

void* min__(PLinkedList list, Compare fun)
{
	void* min_value = list->header->data;
	PNode p = list->header->next;
	while (p != NULL)
	{
		if (fun(min_value, p->data) > 0)
		{
			min_value = p->data;
		}
		p = p->next;
	}

	return min_value;
}

void swap__(PLinkedList list, int i, int j)
{
	PNode p_i = findNode(list, i);
	PNode p_j = findNode(list, j);
	void* t;
	t = p_i->data;
	p_i->data = p_j->data;
	p_j->data = t;
}

void sort__(PLinkedList list, Compare fun)
{
	for (int suo=0 ;suo<size(list)-1 ;suo++ )
	{
		for (int bi=suo+1 ;bi<size(list) ;bi++ )
		{
			if ( fun( get(list,suo),get(list,bi))>0   )
			{
				swap__(list,suo,bi);
			}
		}
	}
}

int binarySearch__(PLinkedList list, void* key, Compare fun)
{
	int left = 0;
	int right = size(list) - 1;
	int mid;
	do
	{
		mid = (left + right) / 2;
		void* mid_data = get(list,mid);
		int cmp = fun(mid_data, key);
		if ( cmp==0 )
		{
			return mid;
		}
		else if (cmp >0 )
		{
			right = mid - 1;
		}
		else
		{
			left = mid + 1;
		}
	} while (left<=right);
	return -mid;
}

void shuffle__(PLinkedList list)
{
	srand((unsigned)time(NULL));
	for (int i=0 ; i<size(list) ; i++)
	{
		int m = rand() % size(list);
		int n = rand() % size(list);
		swap__(list, m, n);
	}
}

void reverse__(PLinkedList list)
{
	void* t;
	int i = 0, j=size(list)-1;
	for (PNode left = list->header,right = list->ender ; i<j ;left=left->next,right=right->prev,i++,j-- )
	{
		t = left->data;
		left->data = right->data;
		right->data = t;
	}
}

void replaceAll__(PLinkedList list, void* oldVal, void* newVal, Compare fun)
{
	PNode p = list->header;
	while ( p )
	{
		if ( fun( oldVal,p->data)==0)
		{
			p->data = newVal;
		}
		p = p->next;
	}
}


四、 本文中所有函数功能列表:

以下是本文代码文件中涉及的功能:

  • 创建链表

  • 创建节点

  • 增加新的节点

  • 在某个位置插入新节点

  • 删除指定下标的节点

  • 删除等于参数的首个节点

  • 通过下标获取节点

  • 通过数据查找相应节点并返回节点数据

  • 对某个下标的节点进行更新

  • 获取某个数据的下标

  • 获取链表中的节点数量

  • 清空链表

  • 迭代器:生成迭代器,判断是否有下一个节点,取得下一个节点的数据

  • 实现栈 stack 的功能:添加元素、弹出元素

  • 实现队列 queue 的功能:在链表头尾添加元素,从头或尾移除元素


  • addAll__:将链表2 追加到链表1的后面

  • max__:返回链表中最大的数据域

  • min__:返回链表中最小的数据域

  • swap__:交换链表中两个下标对应的数据域

  • sort__:对链表按照指定比较规则进行排序

  • binarySearch__:使用折半查找思路在链表中查找某个key的数据域并返回其下标

  • shuffle__:随机打乱链表中元素的顺序

  • reverse__:将链表中的成员进行首尾倒置

  • replaceAll__:将符合指定比较规则的数据域替换为新的数据域

本链表的增删改查功能组件可以被复用在平时的项目中。


大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。

在这里插入图片描述

大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天喜Studio

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

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

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

打赏作者

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

抵扣说明:

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

余额充值