#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;
}
单链表的增删改查以及测试操作
最新推荐文章于 2024-07-12 18:56:03 发布