c 语言 单链表的所有操作

c 语言 单链表的所有操作

单链表的定义:


//静态链表
typedef struct _LinkList {
	int data;//数据
	struct _LinkList* next;//指向下一个节点
	int length;//计算链表的长度;
}LinkList;

//ptrLinkList 是 LinkList指针类型;
typedef LinkList* ptrLinkList;

ptrLinkList 是一个LinkList 结构体的指针类型;

注意: 注释中头结点不是链表的第一个节点,是第一个节点之前的节点,是哨兵,没有实际的作用.


//这原本是一个替别人写的作业,可是价钱没有谈拢,就只能改一下,做成一篇博客了,要不然太亏了😂😂😂

一.链表头结点的初始化


/*
*函数作用:初始化静态链表头结点
* 
*函数参数:head 是一个LinkList 二级指针 
*         //为什么用二级指针 函数传参时指针降级 
*         //需要动态内存分配head一级指针  改变一级指针指向的地址
*
*函数返回值: head 动态内存分配成功 返回1; 否则返回0;
*/
int initLinkList(LinkList** head) {
	if (!head) return 0;

	*head = (LinkList*)malloc(sizeof(LinkList));
	
	if (!*head) return 0;

	(*head)->next = NULL;

	(*head)->data = -1;
	(*head)->length = 0;

	return 1;
}

二.链表的后插法

/*
*函数作用:在静态链表尾追加节点(后插法)
*
*函数参数: head 是静态链表的头结点
*          data 是待插入静态链表节点的数据
*
*函数返回值:插入节点数据成功返回1;否则返回0;
*/
int pushBackLinkList(ptrLinkList head,int data) {
	if (!head) return 0;
	++head->length;
	ptrLinkList temp = NULL;

	temp = (LinkList*)malloc(sizeof(LinkList));
	
	//动态内存分配失败;
	if (!temp) return 0;
	
	temp->data = data;

	while (head->next) {
		head = head->next;
	}

	head->next = temp;
	temp->next = NULL;

	
	return 1;
}

三.链表的前插法

/*
*函数作用:在静态链表第一个节点追加节点(前插法)
*
*函数参数: head 是静态链表前的头结点
*          data 是待插入静态链表节点的数据
*
*函数返回值:插入节点数据成功返回1;否则返回0;
*/
if (!head) return 0;
	++head->length;
	ptrLinkList temp = NULL;

	temp = (LinkList*)malloc(sizeof(LinkList));

	//动态内存分配失败;
	if (!temp) return 0;

	temp->data = data;

	temp -> next =head->next;
	head->next = temp;


	return 1;
}

四.链表的打印

/*
*函数作用:打印全部的静态链表节点数据
*
*函数参数: head 是静态链表的头结点
*
*函数返回值:打印节点数据成功返回1;否则返回0;
*/
int printLinkListData(ptrLinkList head){
	//这个head 指向了空,这个链表为空
	if (!head || !head->next) return 0; 
	printf("\n");
	//插入排序(升序)
	//insertSortLinkList(head);

	ptrLinkList temp = head->next;

	while (temp) {

		printf("%d\t", temp->data);
		
		temp = temp->next;
	}

	printf("\n");

	return 1;
}

五.链表的查找

/*
*函数作用:查找静态链表节点中数据是否有target
*
*函数参数: head 是静态链表的头结点
*        target 是需要查询的数据
*
*函数返回值:找到target数据返回节点地址,否则返回NULL;

*/
ptrLinkList findLinkListData(ptrLinkList head, int target) {
	if (!head || !head->next) return 0;
	

	ptrLinkList temp = head->next;
	
	while (temp) {
		if (temp->data == target) {
			return temp;
		}
		temp = temp->next;
	}
	
	return NULL;

}

六.链表的删除节点中的数据与指定数据相同的节点

/*
*函数作用:节点数据与target相同删除一个节点
*
*函数参数: head 是静态链表的头结点
*          target 是需要删除的节点数据
*
*函数返回值:找到target与节点数据相同的并删除节点返回1,否则返回0;
*/
int deleteLinkListNode(ptrLinkList head,int target) {
	if (!head || !(head->next)) return 0;

	//删除的节点
	ptrLinkList appointNode = head->next;
	//删除节点的上一个节点
	ptrLinkList previousNode = head;
	
	while (appointNode) {
		if (appointNode->data == target) break;
	    
		previousNode = appointNode;
		appointNode = appointNode->next;
	}
     
	if (appointNode) {
		previousNode->next = appointNode -> next;
		free(appointNode);
		--head->length;
		return 1;
	}


	return 0;
}

七.删除指定节点

/*
*函数作用:删除target节点
*
*函数参数: head 是静态链表的头结点
*          target 是一个链表节点地址
*
*函数返回值:找到target与节点地址相同的并删除节点返回1,否则返回0;
*/

int deleteLinkListNode(ptrLinkList head, ptrLinkList target) {
	if (!head || !(head->next))  return 0;

	ptrLinkList appointNode = head->next;
	//删除节点的上一个节点
	ptrLinkList previousNode = head;

	while (appointNode) {
		if (appointNode == target) {
			ptrLinkList tmp = appointNode;
			previousNode->next = appointNode->next;
			appointNode = appointNode->next;
			free(tmp);
			--head->length;
			break;
		}

		previousNode = appointNode;
		appointNode = appointNode->next;
	}

	
	return 0;
}

八. 使用插入排序进行升序排列链表

/*
*函数作用: 使用插入排序进行升序
*
*函数参数: head 是静态链表的头结点
*
*函数返回值: 无
*/
void insertSortLinkList(ptrLinkList head) {
	//当前链表的头结点 
	if (!head || !(head->next) || !(head -> next -> next))return;

	//p 指向的是这个链表的第一个结点
	ptrLinkList p = head->next;
	//pend 指向的是这个链表的第二个节点
	ptrLinkList pend = p->next;
	while (p) {
		//tempHead 先指向 第一个节点 (待插入位置) 
		ptrLinkList tempHead = head -> next;

		//preNode 先指向 头结点(哨兵)  preNode 为插入位置的上一个节点
		ptrLinkList preNode = head;

		//从第一个节点 开始 找到前一个节点的数据比下一个节点数据大的
		//外循环的第二个循环开始就不会再回到第一个节点比较了
		while (pend && (p->data <= pend->data)) {
			p = p->next;
			pend = pend->next;
		}

		
		if (pend) {
			//从第一个节点开始 找 比pend节点中的数据大的插入
			while ( tempHead->data <= pend->data) {
				preNode = tempHead;
				tempHead = tempHead->next;
			}
			

			//保存 pend 指向的下一个节点
			ptrLinkList t = pend->next;
		    
			//前一个节点的next 指向 pend (插入)
			preNode->next = pend;
			//pend  的 next 指向 从第一个节点开始第一个比pend节点中的数据大的
			pend->next = tempHead;
			
			//pend = 它先前保存的下一个节点
			pend = t;

			//先前p 的next 是指向 pend的 pend更新了 p 的 next 指向的也更新
			//p 永远 是 pend 的前一个节点
			p  -> next = pend;

		}
		else {
			break;
		}
	}
}

九,删除重复项

/*
*函数作用:删除链表节点的重复项
*
*函数参数: head 是静态链表的头结点
*
*函数返回值:删除成功返回1,否则返回0;
*/
int deleteRepetitionNode(ptrLinkList head) {
	if (!head || !(head->next) || !(head->next->next)) return 0;

	ptrLinkList slowPtr = head->next;
	ptrLinkList quickPtr = slowPtr->next;

	while (quickPtr) {
	    if (quickPtr->data == slowPtr->data) {
			ptrLinkList temp = quickPtr;
			quickPtr = quickPtr->next;
			deleteLinkListNode(head, temp);
		}
		else {
			slowPtr = slowPtr->next;
			quickPtr = quickPtr->next;
		}
	}
	
	return 1;
}

十.反转链表

/*
*函数作用:反转链表(使用递归和后插法)
*
*函数参数 : head 是静态链表的第一个节点
*
*函数返回值 : 反转成功返回新的第一个节点, 否则返回NULL;
*/
ptrLinkList reversalLinkList(ptrLinkList head) {
	if (!head || !(head->next)) return head; 


	ptrLinkList ret = reversalLinkList(head->next);

	ptrLinkList temp = ret;

	while (temp ->next) {
		temp = temp->next;
	}

	temp->next = head;
	head->next = NULL;

	return ret;
}

十一.链表的二个有序的链表合并成一个有序的链表

/*
*函数作用: 将二个有序的链表合并成一个有序的链表
*
*函数参数:head1 第一个链表的第一个节点
*         head2 第二个链表的第一个节点
*
*函数返回值: 返回合并二个链表后的头结点
*/
ptrLinkList mergerSortLinkList(ptrLinkList head1,ptrLinkList head2) {
	if (!head1 && !head2) return NULL;
	if (!head1) return head2;
	if (!head2) return head1;

	ptrLinkList pStart = NULL;
	initLinkList(&pStart);
	ptrLinkList temp = pStart;

	while (head1 && head2) {
		while (temp->next) temp = temp->next;
		ptrLinkList t = NULL;
		if (head1->data <= head2->data) {
			t = head1->next;
			head1->next = NULL;
			temp->next = head1;
			
			head1 = t;
		}
		else {
			t = head2->next;
			head2->next = NULL;
			temp->next = head2;
			head2 = t;
		}
	}
	while (temp->next) temp = temp->next;

	if (!head1) {
		temp->next = head2;
	}

	if (!head2) {
		temp->next = head1;
	}


	return pStart;
}

十二.请除链表全部节点

*
*函数作用:删除链表的全部节点
*
*函数参数 : head 是静态链表的头节点
*
*函数返回值 : 删除成功返回新的第一个节点, 否则返回NULL;
*/
int deleteLinkList(ptrLinkList head) {
	if (!head) return 0;

	ptrLinkList temp = head;

	while (temp) {
		head = head->next;
		free(temp);
		temp = head;
	}

	return 0;
}

最后是我便于复制粘贴的代码可忽略

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>

//静态链表
typedef struct _LinkList {
	int data;//数据
	struct _LinkList* next;//指向下一个节点
	int length;//每增加一个节点++;
}LinkList;

//ptrLinkList 是 LinkList指针类型;
typedef LinkList* ptrLinkList;

/*
*函数作用:初始化静态链表头结点
* 
*函数参数:head 是一个LinkList 二级指针 
*         //为什么用二级指针 函数传参时指针降级 
*         //需要动态内存分配head一级指针  改变一级指针指向的地址
*
*函数返回值: head 动态内存分配成功 返回1; 否则返回0;
*/
int initLinkList(LinkList** head);

/*
*函数作用:在静态链表尾追加节点(后插法)
*
*函数参数: head 是静态链表的头结点
*          data 是待插入静态链表节点的数据
*
*函数返回值:插入节点数据成功返回1;否则返回0;
*/
int pushBackLinkList(ptrLinkList head, int data);


/*
*函数作用:在静态链表第一个节点前追加节点(前插法)
*
*函数参数: head 是静态链表的头结点
*          data 是待插入静态链表节点的数据
*
*函数返回值:插入节点数据成功返回1;否则返回0;
*/
int pushFrontLinkList(ptrLinkList head, int data);

/*
*函数作用:打印全部的静态链表节点数据
*
*函数参数: head 是静态链表的头结点
*
*函数返回值:打印节点数据成功返回1;否则返回0;
*/
int printLinkListData(ptrLinkList head);

/*
*函数作用:返回静态链表的节点数
*
*函数参数: head 是静态链表的头结点
*
*函数返回值:返回节点的个数
*/
int lengthLinkList(ptrLinkList head);


/*
*函数作用:查找静态链表节点中数据是否有target
*
*函数参数: head 是静态链表的头结点
*          target 是需要查询的数据
*
*函数返回值:找到target数据返回节点地址,否则返回NULL;
*/
ptrLinkList findLinkListData(ptrLinkList head,int target);

/*
*函数作用:节点数据与target相同删除一个节点
*
*函数参数: head 是静态链表的头结点
*          target 是需要删除的节点数据
*
*函数返回值:找到target与节点数据相同的并删除节点返回1,否则返回0;
*/
int deleteLinkListNode(ptrLinkList head, int target);

/*
*函数作用:删除target节点
*
*函数参数: head 是静态链表的头结点
*          target 是一个链表节点地址
*
*函数返回值:找到target与节点地址相同的并删除节点返回1,否则返回0;
*/
int deleteLinkListNode(ptrLinkList head,  ptrLinkList target);

/*
*函数作用:删除与target数据相同的节点数据的所有节点;
*
*函数参数: head 是静态链表的头结点
*          target 是一个链表节点
*
*函数返回值:找到target与节点数据相同的并删除节点返回1,否则返回0;
*/
//int deleteLinkListNodes(ptrLinkList head,int target);

/*
*函数作用: 使用插入排序进行升序
*
*函数参数: head 是静态链表的头结点
*
*函数返回值: 无
*/
static void insertSortLinkList(ptrLinkList head);

/*
*函数作用:删除链表节点的重复项
*
*函数参数: head 是静态链表的头结点
*
*函数返回值:删除成功返回1,否则返回0;
*/
int deleteRepetitionNode(ptrLinkList head);

/*
*函数作用:反转链表(使用递归和后插法)
*
*函数参数 : head 是静态链表的第一个节点
*
*函数返回值 : 反转成功返回新的第一个节点, 否则返回NULL;
*/
ptrLinkList reversalLinkList(ptrLinkList head);

/*
*函数作用: 将二个有序的链表合并成一个有序的链表
*
*函数参数:head1 第一个链表的第一个节点
*         head2 第二个链表的第一个节点
*
*函数返回值: 返回合并二个链表后的头结点
*/
ptrLinkList mergerSortLinkList(ptrLinkList head1,ptrLinkList head2);

/*
*函数作用:删除链表的全部节点
*
*函数参数 : head 是静态链表的头节点
*
*函数返回值 : 删除成功返回新的第一个节点, 否则返回NULL;
*/
int deleteLinkList(ptrLinkList head);

int main(void) {
	
	//头结点head 和 head1 不存数据 哨兵
	ptrLinkList head = NULL;
	ptrLinkList head1 = NULL;
	ptrLinkList mergerHead = NULL;

	//需要删除的元素值
	int element; 

	//链表长度;
	int length; 

	//需要插入节点的个数
	int n = 0;  

	initLinkList(&head);
	initLinkList(&head1);

	printf("pleass input link list node amount:");

	scanf_s("%d", &n);

	//设置随机种子 如果不设置 rand() 生成的数据是伪随机数
	srand((unsigned int)time(0));

	for (int i = 0; i < n; i++) {
		//rand() 随机数据
		//在静态链表尾追加一个节点 ,这个节点的数据 就是 rand()生成的数据
		pushFrontLinkList(head, n -i);
		pushBackLinkList(head1, rand() % 10);
	}
	
	printf("\n");
    
	
	//打印全部的静态链表节点数据
	printf("print link list head :\n");
	printLinkListData(head);
	printf("print link list head1 :\n");
	printLinkListData(head1);



    /*length = lengthLinkList(head);
	printf("\n");
	printf("link list length:%d", length)*/;
	
	/*printf("after Link List head that reversal:\n");
	head ->next =reversalLinkList(head->next);*/


	printf("after tow Link List merger:\n");
	mergerHead = mergerSortLinkList(head->next, head1->next);
	

	//deleteRepetitionNode(head);
	
	printLinkListData(mergerHead);
	printf("pleass input  data that you need remove :");
	scanf_s("%d", &element);

	deleteLinkListNode(mergerHead, element);
	printLinkListData(mergerHead);

	/*length = lengthLinkList(head);
	printf("link list length:%d", length);*/
	printf("\n");
	
	printf("delete all link list\n");

	deleteLinkList(mergerHead);

	return 0;
}

int initLinkList(LinkList** head) {
	if (!head) return 0;

	*head = (LinkList*)malloc(sizeof(LinkList));
	
	if (!*head) return 0;

	(*head)->next = NULL;

	(*head)->data = -1;
	(*head)->length = 0;

	return 1;
}

int pushBackLinkList(ptrLinkList head,int data) {
	if (!head) return 0;
	++head->length;
	ptrLinkList temp = NULL;

	temp = (LinkList*)malloc(sizeof(LinkList));
	
	//动态内存分配失败;
	if (!temp) return 0;
	
	temp->data = data;

	while (head->next) {
		head = head->next;
	}

	head->next = temp;
	temp->next = NULL;

	
	return 1;
}

int pushFrontLinkList(ptrLinkList head, int data) {
	if (!head) return 0;
	++head->length;
	ptrLinkList temp = NULL;

	temp = (LinkList*)malloc(sizeof(LinkList));

	//动态内存分配失败;
	if (!temp) return 0;

	temp->data = data;

	temp -> next =head->next;
	head->next = temp;


	return 1;
}


int printLinkListData(ptrLinkList head){
	//这个head 指向了空,这个链表为空
	if (!head || !head->next) return 0; 
	printf("\n");
	//插入排序(升序)
	//insertSortLinkList(head);

	ptrLinkList temp = head->next;

	while (temp) {

		printf("%d\t", temp->data);
		
		temp = temp->next;
	}

	printf("\n");


	return 1;
}

int lengthLinkList(ptrLinkList head) {
	if (!head || !head -> next) return 0;

	return head->length;
}


ptrLinkList findLinkListData(ptrLinkList head, int target) {
	if (!head || !head->next) return 0;
	
	ptrLinkList temp = head->next;

	while (temp) {
		if (temp->data == target) {
			return temp;
		}
		temp = temp->next;
	}

	return NULL;
}




void insertSortLinkList(ptrLinkList head) {
	//当前链表的头结点 
	if (!head || !(head->next) || !(head -> next -> next))return;

	//p 指向的是这个链表的第一个结点
	ptrLinkList p = head->next;
	//pend 指向的是这个链表的第二个节点
	ptrLinkList pend = p->next;
	while (p) {
		//tempHead 先指向 第一个节点 (待插入位置) 
		ptrLinkList tempHead = head -> next;

		//preNode 先指向 头结点(哨兵)  preNode 为插入位置的上一个节点
		ptrLinkList preNode = head;

		//从第一个节点 开始 找到前一个节点的数据比下一个节点数据大的
		//外循环的第二个循环开始就不会再回到第一个节点比较了
		while (pend && (p->data <= pend->data)) {
			p = p->next;
			pend = pend->next;
		}

		
		if (pend) {
			//从第一个节点开始 找 比pend节点中的数据大的插入
			while ( tempHead->data <= pend->data) {
				preNode = tempHead;
				tempHead = tempHead->next;
			}
			

			//保存 pend 指向的下一个节点
			ptrLinkList t = pend->next;
		    
			//前一个节点的next 指向 pend (插入)
			preNode->next = pend;
			//pend  的 next 指向 从第一个节点开始第一个比pend节点中的数据大的
			pend->next = tempHead;
			
			//pend = 它先前保存的下一个节点
			pend = t;

			//先前p 的next 是指向 pend的 pend更新了 p 的 next 指向的也更新
			//p 永远 是 pend 的前一个节点
			p  -> next = pend;

		}
		else {
			break;
		}
	}


}

int deleteLinkListNode(ptrLinkList head,int target) {
	if (!head || !(head->next)) return 0;

	//删除的节点
	ptrLinkList appointNode = head->next;
	//删除节点的上一个节点
	ptrLinkList previousNode = head;
	
	while (appointNode) {
		if (appointNode->data == target) break;
	    
		previousNode = appointNode;
		appointNode = appointNode->next;
	}
     
	if (appointNode) {
		previousNode->next = appointNode -> next;
		free(appointNode);
		--head->length;
		return 1;
	}


	return 0;
}

int deleteRepetitionNode(ptrLinkList head) {
	if (!head || !(head->next) || !(head->next->next)) return 0;

	ptrLinkList slowPtr = head->next;
	ptrLinkList quickPtr = slowPtr->next;

	while (quickPtr) {
	    if (quickPtr->data == slowPtr->data) {
			ptrLinkList temp = quickPtr;
			quickPtr = quickPtr->next;
			deleteLinkListNode(head, temp);
		}
		else {
			slowPtr = slowPtr->next;
			quickPtr = quickPtr->next;
		}
	}
	
	return 1;
}
 

int deleteLinkListNode(ptrLinkList head, ptrLinkList target) {
	if (!head || !(head->next))  return 0;

	ptrLinkList appointNode = head->next;
	//删除节点的上一个节点
	ptrLinkList previousNode = head;

	while (appointNode) {
		if (appointNode == target) {
			ptrLinkList tmp = appointNode;
			previousNode->next = appointNode->next;
			appointNode = appointNode->next;
			free(tmp);
			--head->length;
			break;
		}

		previousNode = appointNode;
		appointNode = appointNode->next;
	}

	

	return 0;
}


ptrLinkList reversalLinkList(ptrLinkList head) {
	if (!head || !(head->next)) return head; 


	ptrLinkList ret = reversalLinkList(head->next);

	ptrLinkList temp = ret;

	while (temp ->next) {
		temp = temp->next;
	}

	temp->next = head;
	head->next = NULL;

	return ret;
}

ptrLinkList mergerSortLinkList(ptrLinkList head1,ptrLinkList head2) {
	if (!head1 && !head2) return NULL;
	if (!head1) return head2;
	if (!head2) return head1;

	ptrLinkList pStart = NULL;
	initLinkList(&pStart);
	ptrLinkList temp = pStart;

	while (head1 && head2) {
		while (temp->next) temp = temp->next;
		ptrLinkList t = NULL;
		if (head1->data <= head2->data) {
			t = head1->next;
			head1->next = NULL;
			temp->next = head1;
			
			head1 = t;
		}
		else {
			t = head2->next;
			head2->next = NULL;
			temp->next = head2;
			head2 = t;
		}
	}
	while (temp->next) temp = temp->next;

	if (!head1) {
		temp->next = head2;
	}

	if (!head2) {
		temp->next = head1;
	}


	return pStart;
}


int deleteLinkList(ptrLinkList head) {
	if (!head) return 0;

	ptrLinkList temp = head;

	while (temp) {
		head = head->next;
		free(temp);
		temp = head;
	}

	return 0;
}

next;
}

temp->next = head;
head->next = NULL;

return ret;

}

ptrLinkList mergerSortLinkList(ptrLinkList head1,ptrLinkList head2) {
if (!head1 && !head2) return NULL;
if (!head1) return head2;
if (!head2) return head1;

ptrLinkList pStart = NULL;
initLinkList(&pStart);
ptrLinkList temp = pStart;

while (head1 && head2) {
	while (temp->next) temp = temp->next;
	ptrLinkList t = NULL;
	if (head1->data <= head2->data) {
		t = head1->next;
		head1->next = NULL;
		temp->next = head1;
		
		head1 = t;
	}
	else {
		t = head2->next;
		head2->next = NULL;
		temp->next = head2;
		head2 = t;
	}
}
while (temp->next) temp = temp->next;

if (!head1) {
	temp->next = head2;
}

if (!head2) {
	temp->next = head1;
}


return pStart;

}

int deleteLinkList(ptrLinkList head) {
if (!head) return 0;

ptrLinkList temp = head;

while (temp) {
	head = head->next;
	free(temp);
	temp = head;
}

return 0;

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值