1.初始化单链表
- 将头结点指向空。
2.尾插
- 空链表,直接插在头结点上
- 非空链表,找到最后一个结点,指向插入的结点
3.尾删
- 空链表,直接返回
- 只有一个结点,直接删除当前头结点,并将head指向空
- 否则,找到倒数第二个结点,将其指向空
4.头插
- 空链表,直接插在头结点上
- 创建新的结点,指向头结点,并更新head指向
5.头删
- 空链表,直接返回
- 非空链表,直接将head指针指向下一个
6.查找元素在链表中的位置
- 遍历链表
7.在pos之前插入元素
- 对于空链表来说,pos无意义,只能把这个元素作为唯一的节点,并让头结点指针指向这个节点
- pos若指向头结点,无法找到pos之前结点,处理成头插
- 找到pos的前一个位置cur,插入;若未找到pos直接返回
8.在pos之后插入元素
- 对于空链表来说,pos无意义,只能把这个元素作为唯一的节点,并让头结点指针指向这个节点
- 非空直接插入
9.删除指定位置的元素
- 空链表,删除失败
- 要删除的刚好是头结点,修改head指向即可
- pos指向任何位置,此时需要找到pos的前一个位置,然后进行删除
- pos在链表上不存在,直接返回
10.删除指定值的元素
- 空链表,删除失败
- 非空,找到该元素,删除
11.删除指定值的所有元素
- 空链表,删除失败
- 非空,通过循环找到指定值的所以元素,删除
12.判断链表是否为空
- 为空返回1,否则返回0
13.求链表元素个数
- 遍历链表,返回元素个数
具体实现代码:
①linklist.h
#pragma once
#include <stddef.h>
#include <stdio.h>
typedef char LinkType;
typedef struct LinkNode{
LinkType data;
struct LinkNode* next;
}LinkNode;
void LinkListInit(LinkNode** head); //初始化
void LinkListPrintChar(LinkNode* head, const char* msg); //打印链表
LinkNode* LinkListPushBack(LinkNode** head, LinkType value); //尾插
void LinkListPopBack(LinkNode** head); //尾删
void LinkListPushFront(LinkNode** head, LinkType value); //头插
void LinkListPopFront(LinkNode** head); //头删
LinkNode* LinkListFind(LinkNode* head, LinkType to_find); //查找元素在链表中的位置
void LinkListInsert(LinkNode** head, LinkNode* pos, LinkType value); //在pos之前插入元素
void LinkListInsertAfter(LinkNode** head, LinkNode* pos, LinkType value); //在pos之后插入元素
void LinkListErase1(LinkNode** head, LinkNode* pos); //删除指定位置的元素
void LinkListErase2(LinkNode** head, LinkNode** pos);
void LinkListRemove1(LinkNode** head, LinkType value); //删除指定值的元素
void LinkListRemove2(LinkNode** head, LinkType value);
void LinkListRemoveAll(LinkNode** head, LinkType value); //删除指定值的所有元素
int LinkListEmpty(LinkNode* head); //判断链表是否为空,为空返回1,否则返回0
size_t LinkListSize(LinkNode* head); //求链表元素个数
②linklist.c
#include "linklist.h"
#include <stdlib.h>
void LinkListInit(LinkNode** head) //初始化
{
if (head == NULL) //非法操作
{
return;
}
*head = NULL;
}
LinkNode* LinkListCreateNode(LinkType value) //创建结点
{
LinkNode* ptr = (LinkNode *)malloc(sizeof(LinkNode));
ptr->data = value;
ptr->next = NULL;
return ptr;
}
void LinkListDestroyNode(LinkNode* ptr) //销毁结点
{
free(ptr);
}
void LinkListPrintChar(LinkNode* head, const char* msg) //打印链表
{
printf("[%s]:", msg);
LinkNode* cur = head;
for (; cur != NULL; cur = cur->next)
{
printf("[%c:%p] -> ", cur->data, cur);
}
printf("[NULL]\n\n");
}
LinkNode* LinkListPushBack(LinkNode** head, LinkType value) //尾插
{
if (head == NULL) //非法输入
{
return NULL;
}
if (*head == NULL) //空链表,直接插在头结点上
{
*head = LinkListCreateNode(value);
return *head;
}
LinkNode* cur = *head;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = LinkListCreateNode(value);
return cur->next;
}
void LinkListPopBack(LinkNode** head) //尾删
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,什么也不干
}
LinkNode* cur = *head;
if (cur->next == NULL)
{
//只有一个结点,直接删除当前头结点
LinkListDestroyNode(cur);
*head = NULL;
return;
}
while (cur->next != NULL)
{
if (cur->next->next == NULL)
{
//找到倒数第二个结点
LinkNode* to_delete = cur->next;
cur->next = NULL;
LinkListDestroyNode(to_delete);
}
else
{
cur = cur->next;
}
}
return;
}
void LinkListPushFront(LinkNode** head, LinkType value) //头插
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL) //空链表,直接插在头结点上
{
*head = LinkListCreateNode(value);
return;
}
LinkNode* new_node = LinkListCreateNode(value);
new_node->next = *head;
*head = new_node;
return;
}
void LinkListPopFront(LinkNode** head) //头删
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,什么也不干
}
LinkNode* to_delete = *head;
*head = (*head)->next;
LinkListDestroyNode(to_delete);
}
LinkNode* LinkListFind(LinkNode* head, LinkType to_find) //查找元素在链表中的位置
{
LinkNode* cur = head;
for (; cur != NULL; cur = cur->next)
{
if (cur->data == to_find)
{
return cur;
}
}
return NULL;
}
void LinkListInsert(LinkNode** head, LinkNode* pos, LinkType value) //在pos之前插入元素
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
//对于空链表来说,pos无意义,只能把这个元素作为唯一的节点,并让头结点指针指向这个节点
*head = LinkListCreateNode(value);
return;
}
if (*head == pos)
{
//pos指向头结点,无法找到pos之前结点,处理成头插
LinkListPushFront(head, value);
return;
}
if (pos == NULL)
{
LinkListPushBack(head, value);
return;
}
LinkNode* cur = *head;
while(cur->next != NULL)
{
if (cur->next == pos)
{
//找到pos的前一个位置cur,插入
LinkNode* new_node = LinkListCreateNode(value);
new_node->next = pos;
cur->next = new_node;
return;
}
else
{
cur = cur->next;
}
}
//未找到pos,直接返回
return;
}
void LinkListInsertAfter(LinkNode** head, LinkNode* pos, LinkType value) //在pos之后插入元素
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
//对于空链表来说,pos无意义,只能把这个元素作为唯一的节点,并让头结点指针指向这个节点
*head = LinkListCreateNode(value);
return;
}
if (pos == NULL)
{
return; //非法输入
}
LinkNode* new_node = LinkListCreateNode(value);
new_node->next = pos->next;
pos->next = new_node;
}
void LinkListErase1(LinkNode** head, LinkNode* pos) //删除指定位置的元素
{
if (head == NULL || pos == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,删除失败
}
if (*head == pos)
{
//要删除的刚好是头结点,修改head指向即可
LinkNode* to_delete = *head;
*head = (*head)->next;
LinkListDestroyNode(to_delete);
return;
}
//pos指向任何位置,此时需要找到pos的前一个位置
LinkNode* cur = *head;
while (cur->next != NULL)
{
if (cur->next == pos)
{
//进行删除动作
cur->next = pos->next;
LinkListDestroyNode(pos);
return;
}
else
{
cur = cur->next;
}
}
return; //pos在链表上不存在
}
void LinkListErase2(LinkNode** head, LinkNode** pos)
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,删除失败
}
if (*pos != NULL && (*pos)->next != NULL)
{
(*pos)->data = (*pos)->next->data;
LinkNode* to_delete = (*pos)->next;
(*pos)->next = to_delete->next;
LinkListDestroyNode(to_delete);
return;
}
if ((*pos)->next == NULL)
{
LinkNode* to_delete = *pos;
*pos = NULL;
LinkListDestroyNode(to_delete);
return;
}
}
void LinkListRemove1(LinkNode** head, LinkType value) //删除指定值的元素
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,删除失败
}
LinkNode* pos = LinkListFind(*head, value);
LinkListErase1(head, pos);
}
void LinkListRemove2(LinkNode** head, LinkType value)
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,删除失败
}
if ((*head)->data == value) //要删除的是头结点
{
LinkNode* to_delete = *head;
*head = (*head)->next;
LinkListDestroyNode(to_delete);
return;
}
LinkNode* pre = *head;
LinkNode* cur = (*head)->next;
while (cur != NULL)
{
if (cur->data == value)
{
pre->next = cur->next;
LinkListDestroyNode(cur);
return;
}
else
{
pre = pre->next;
cur = cur->next;
}
}
//要删除的元素不存在,直接返回
return;
}
void LinkListRemoveAll(LinkNode** head, LinkType value) //删除指定值的所有元素
{
if (head == NULL)
{
return; //非法输入
}
if (*head == NULL)
{
return; //空链表,删除失败
}
while (1)
{
LinkNode* pos = LinkListFind(*head, value);
if (pos == NULL)
{
break;
}
LinkListErase1(head, pos);
}
return;
}
int LinkListEmpty(LinkNode* head) //判断链表是否为空,为空返回1,否则返回0
{
return head == NULL ? 1 : 0;
}
size_t LinkListSize(LinkNode* head) //求链表元素个数
{
if (head == NULL)
{
return 0; //空链表
}
size_t count = 0;
LinkNode* cur = head;
while (cur != NULL)
{
++count;
cur = cur->next;
}
return count;
}
③test.c
#include "linklist.h"
#include <windows.h>
#define TEST_HEADER printf("\n========================================%s===========================================\n",__FUNCTION__)
void TestInit()
{
LinkNode* head;
LinkListInit(&head);
printf("head = %p,%ld\n", head,(long)head);
}
void TestPushBack()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
}
void TestPopBack()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPopBack(&head);
LinkListPrintChar(head, "尝试对空链表尾删");
LinkListPushBack(&head, 'a');
LinkListPopBack(&head);
LinkListPrintChar(head, "尝试对只有一个元素链表尾删");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkListPopBack(&head);
LinkListPopBack(&head);
LinkListPrintChar(head, "尾删两个个元素");
}
void TestPushFront()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushFront(&head, 'a');
LinkListPushFront(&head, 'b');
LinkListPushFront(&head, 'c');
LinkListPushFront(&head, 'd');
LinkListPrintChar(head, "头插四个元素");
}
void TestPopFront()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPopFront(&head);
LinkListPrintChar(head, "尝试对空链表头删");
LinkListPushFront(&head, 'a');
LinkListPushFront(&head, 'b');
LinkListPushFront(&head, 'c');
LinkListPushFront(&head, 'd');
LinkListPrintChar(head, "头插四个元素");
LinkListPopFront(&head);
LinkListPopFront(&head);
LinkListPrintChar(head, "头删两个元素");
LinkListPopFront(&head);
LinkListPopFront(&head);
LinkListPrintChar(head, "再头删两个元素");
}
void TestFind()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkNode* pos_c = LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkNode* pos = LinkListFind(head, 'e');
printf("[查找e]:pos expect NULL,actual %p\n", pos);
pos = LinkListFind(head, 'c');
printf("[查找c]:pos expect %p,actual %p\n", pos_c, pos);
}
void TestInsert()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListInsert(&head, head, 'b');
LinkListPrintChar(head, "对空链表插入");
LinkListInsert(&head, head, 'a');
LinkListPrintChar(head, "对只有头结点链表插入");
LinkNode* pos = LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插一个元素");
LinkListInsert(&head, pos, 'c');
LinkListPrintChar(head, "在d之前插入");
LinkListInsert(&head, NULL, 'e');
LinkListPrintChar(head, "在链表尾部插入");
}
void TestInsertAfter()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListInsertAfter(&head, head, 'a');
LinkListPrintChar(head, "对空链表插入");
LinkListInsertAfter(&head, head, 'b');
LinkListPrintChar(head, "对只有头结点链表插入");
LinkNode* pos = LinkListPushBack(&head, 'c');
LinkListPrintChar(head, "尾插一个元素");
LinkListInsertAfter(&head, pos, 'd');
LinkListPrintChar(head, "在c之后插入");
}
void TestErase1()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListErase1(&head, NULL);
LinkListPrintChar(head, "尝试对空链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkNode* pos_c = LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkListErase1(&head, pos_c);
LinkListPrintChar(head, "删除元素c");
}
void TestErase2()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListErase2(&head, NULL);
LinkListPrintChar(head, "尝试对空链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkNode* pos_c = LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkListErase2(&head, &pos_c);
LinkListPrintChar(head, "删除元素c");
}
void TestRemove1()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkListRemove1(&head, 'e');
LinkListPrintChar(head, "尝试删除不存在元素e");
LinkListRemove1(&head, 'c');
LinkListPrintChar(head, "尝试删除元素c");
}
void TestRemove2()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
LinkListRemove2(&head, 'e');
LinkListPrintChar(head, "尝试删除不存在元素e");
LinkListRemove2(&head, 'c');
LinkListPrintChar(head, "尝试删除元素c");
}
void TestRemoveAll()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListRemoveAll(&head, 'a');
LinkListPrintChar(head, "尝试对空链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插七个元素");
LinkListRemoveAll(&head, 'e');
LinkListPrintChar(head, "尝试删除不存在元素e");
LinkListRemoveAll(&head, 'c');
LinkListPrintChar(head, "尝试删除元素c");
}
void TestEmpty()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
int ret = LinkListEmpty(head);
printf("ret expect 1,actual %d\n", ret);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
ret = LinkListEmpty(head);
printf("ret expect 0,actual %d\n", ret);
}
void TestSize()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
size_t ret = LinkListSize(head);
printf("ret expect 0,actual %d\n", ret);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPrintChar(head, "尾插四个元素");
ret = LinkListSize(head);
printf("ret expect 4,actual %d\n", ret);
}
int main()
{
TestInit();
TestPushBack();
TestPopBack();
TestPushFront();
TestPopFront();
TestFind();
TestInsert();
TestInsertAfter();
TestErase1();
TestErase2();
TestRemove1();
TestRemove2();
TestRemoveAll();
TestEmpty();
TestSize();
system("pause");
return 0;
}
结果:
未完待续。。。