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;
}