单链表的增删改查以及测试操作

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

typedef struct LinkNode {
	int data;
	struct LinkNode* next;
} LinkNode, * LinkList;

//链表的初始化
LinkList initList() {
	LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode));
	p->data = 0;
	p->next = NULL;
	return p;
}

//求链表的长度
int listLength(LinkList L) {
	LinkNode* p = L->next;
	int i;
	for (i = 0; p != NULL; i++) {
		p = p->next;
	}
	return i;
}

//按位查找
int getElem(LinkList L, int i) {
	LinkNode* p = L->next;
	for (int k = 0; k < i; k++) {
		p = p->next;
		if (p == NULL) {
			return -1;
		}
	}
	return p->data;
}

//按值查找
int locateElem(LinkList L, int e) {
	LinkNode* p = L->next;
	for (int i = 0; p != NULL; i++) {
		if (p->data == e) {
			return i;
		}
		p = p->next;
	}
	return -1;
}

//遍历单链表
void listVisit(LinkList L) {
	LinkNode* p = L->next;
	for (; p != NULL; p = p->next) {
		printf("%d ", p->data);
	}
	printf("\n");
}

//单链表插入元素
bool listInsert(LinkList* L, int i, int e) {
	LinkNode* p = *L;
	for (int j = 0; j < i-1; j++) {
		p = p->next;
		if (p == NULL) {
			return false;
		}
	}
	LinkNode* q = (LinkNode*)malloc(sizeof(LinkNode));
	q->data = e;
	q->next = p->next;
	p->next = q;
	return true;
}

//单链表删除元素
bool listDelete(LinkList* L, int i, int* e) {
	LinkNode* p = *L;
	for (int j = 0; j < i-1; j++) {
		p = p->next;
		if (p == NULL) {
			return false;
		}
	}
	if (p->next == NULL) {
		return false;
	}
	LinkNode* q = p->next; //指向被删除的位置
	*e = q->data;
	p->next = q->next;
	free(q);
	return true;
}

//单链表置空
void clearList(LinkList* L) {
	LinkNode* p = (*L)->next;
	for (; p != NULL;) {
		LinkNode* temp = p->next;
		free(p);
		p = temp;
	}
	(*L)->next = NULL;
}

//单链表判空
bool listEmpty(LinkList L) {
	LinkNode* p = L->next;
	if (p == NULL) {
		return true;
	}
	return false;
}
//原地倒置单链表
void listReverse1(LinkList *L){
	LinkNode *p=(*L)->next,*pprev=NULL,*pnext=NULL;
	if(p==NULL||p->next==NULL)
		return;
	while(p!=NULL){
		pnext=p->next;
		p->next=pprev;
		pprev=p;
		p=pnext;
	}
	(*L)->next=pprev;
}

//递归实现单链表的逆置1
LinkList listReverse2(LinkNode* p){
	if (p == NULL || p->next == NULL) {
		return p;
	}
	
	LinkNode* newHead = listReverse2(p->next);
	p->next->next = p;
	p->next = NULL;
	
	return newHead;
}
LinkList listReverse2Wrapper(LinkList L) {
	if (L == NULL || L->next == NULL) {
		return L;
	}
	L->next = listReverse2(L->next);
	return L;
}
//递归实现单链表的逆置2
LinkList listReverse3(LinkList L) {
	if (L == NULL || L->next == NULL) {
		return L;
	}
	
	LinkNode* p = L->next;
	LinkNode* newHead = listReverse2(p->next);
	p->next->next = p;
	p->next = NULL;
	L->next = newHead;
	
	return L;
}
//双指针遍历单链表
LinkNode *findKFromLast(LinkList L,int k){
	LinkNode* fast = L;
	LinkNode* slow = L;
	int count = 0;
	while (fast != NULL && count <= k) {
		fast = fast->next;
		count++;
	}
	if (count < k)
		return NULL;
	while (fast != NULL) {
		fast = fast->next;
		slow = slow->next;
	}
	return slow;
}

//使用快慢指针判断单链表是否有环
bool hasRing(LinkList L){
	LinkNode *fast=L;
	LinkNode *slow=L;
	while(fast!=NULL&&fast->next!=NULL){
		fast=fast->next->next;
		slow=slow->next;
		if(fast==slow)
			return true;
	}
	return false;
}

int main() {
	LinkList list = initList(); // 初始化链表
	
	// 在链表末尾插入元素
	listInsert(&list, 1, 10);
	listInsert(&list, 2, 20);
	listInsert(&list, 3, 30);
	listInsert(&list, 0, 40);
	
	// 输出链表内容
	printf("链表内容:");
	listVisit(list);
	
	//使用快慢指针判断单链表是否有环
	printf("使用快慢指针判断单链表是否有环:");
	printf("%d\n",hasRing(list));
	
	// 输出原地逆置后的链表内容
	printf("原地逆置后的链表内容:");
	listReverse1(&list);
	listVisit(list);
	
	// 输出递归逆置后的链表内容
	printf("递归逆置后的链表内容:");
	list=listReverse2Wrapper(list);
	listVisit(list);
	
	// 输出递归逆置后的链表内容
	printf("递归逆置后的链表内容:");
	list=listReverse3(list);
	listVisit(list);
	
	// 双指针遍历后的链表内容
	printf("双指针遍历后的链表内容:");
	list=findKFromLast(list,2);
	listVisit(list);
	
	// 获取链表长度
	int length = listLength(list);
	printf("链表长度:%d\n", length);
	
	// 按位查找
	int elem = getElem(list, 2);
	printf("第2个位置的元素:%d\n", elem);
	
	// 按值查找
	int index = locateElem(list, 20);
	printf("元素20的位置:%d\n", index);
	
	// 删除元素
	int deletedElem;
	listDelete(&list, 2, &deletedElem);
	printf("删除的元素:%d\n", deletedElem);
	
	// 输出删除元素后的链表
	printf("删除元素后的链表:");
	listVisit(list);
	
	// 判断链表是否为空
	bool isEmpty = listEmpty(list);
	printf("链表是否为空:%s\n", isEmpty ? "是" : "否");
	
	// 清空链表
	clearList(&list);
	
	// 判断链表是否为空
	isEmpty = listEmpty(list);
	printf("清空链表后,链表是否为空:%s\n", isEmpty ? "是" : "否");
	
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ac果

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

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

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

打赏作者

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

抵扣说明:

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

余额充值