C语言不带头结点的单链表
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
struct node* next;
int data;
} Lnode, * LinkList;
//初始化(不带头节点的单链表)
//如果头指针不是空,则置为空
void initSingleLinkList(Lnode* head) {
if (head)
{
head = NULL;
}
}
//链表的销毁(不带头节点的单链表)
void destroy(Lnode* L) {
Lnode* p;
while (L != NULL)
{
p = L;
L = L->next;
free(p);
}
}
//清空链表中所有的元素
void clear(Lnode* L) {
Lnode* p = L->next;
Lnode* q;
while (p != NULL)
{
q = p;
p = p->next;
free(q);
}
L->data = NULL;
L->next = NULL;
}
//不带头节点的单链表,头插法
void headInsert(LinkList* L, int e) {
Lnode* pNode = (Lnode*)malloc(sizeof(Lnode));
pNode->data = e;
pNode->next = *L;
*L = pNode;
}
//不带头节点的单链表,尾插法
//这里是通过遍历链表到最后一个节点,然后在最后一个节点后面插入新的节点
//也可以通过维护一个尾指针,直接利用尾指针插入新的节点,再维护尾指针
void tailInsert(LinkList* L, int e) {
Lnode* pNode = (Lnode*)malloc(sizeof(Lnode*));
pNode->data = e;
pNode->next = NULL;
if (!L)
{
*L = pNode;
}
else
{
Lnode* p = *L;
while (p->next)
{
p = p->next;
}
p->next = pNode;
}
}
//链表的遍历输出
void show(Lnode* L) {
if (!L)
{
printf("L为空\n");
return;
}
else
{
Lnode* p = L;
int i = 0;
while (p)
{
printf("链表中的第%d个元素是%d\n", i++, p->data);
p = p->next;
}
}
}
//判断链表是否包含某个元素
bool contains(Lnode* L, int e) {
if (!L)
{
return false;
}
else
{
Lnode* p = L;
while (p)
{
if (p->data == e) {
return true;
}
p = p->next;
}
return false;
}
}
//删除链表中的某个元素(第一次出现的目标元素节点)
bool delete(Lnode* L, int e) {
if (!L)
{
return false;
}
else if (L->data == e)
{
L = L->next;
}
else
{
Lnode* p = L->next;
Lnode* q = L;
while (p)
{
if (p->data == e)
{
q->next = p->next;
free(p);
return true;
}
q = p;
p = p->next;
}
}
}
//删除第i个位置的节点,返回删除节点的数据域
bool deleteIndex(LinkList* L, int index,int* e) {
if (! (*L) || index < 0)
{
*e = -1;
return false;
}
//如果删除的是首元节点,首元节点后无节点,则链表为空,有节点,则下一个节点为首元节点
if (*L && index == 0) {
if (!(*L)->next)
{
*e = (*L)->data;
free(L);
return true;
}
else
{
*e = (*L)->data;
Lnode* p = (*L);
(*L) = (*L)->next;
free(p);
return true;
}
}
//如果删除的是中间的普通节点,则需要将该节点的前驱节点的next指向该节点的后一个节点
Lnode* p = *L;
int i = 0;
while (p->next)
{
if (i == index-1)
{
*e = p->next->data;
p->next = p->next->next;
return true;
}
i++;
p = p->next;
}
*e = -1;
return false;
//如果删除的是尾节点,则不需要将尾节点的前一个节点的next域指向尾节点的后一个节点
}
//链表中元素的个数
int size(Lnode* L) {
if (!L)
{
Lnode* p = L;
int i = 0;
while (!p)
{
i++;
p = p->next;
}
return i;
}
return -1;
}
//链表的逆序
Lnode* reversedAtNode(LinkList* head, Lnode* pNode) {
if (pNode->next == NULL)
{
*head = pNode;
}
else
{
(reversedAtNode(head, pNode->next))->next = pNode;
pNode->next = NULL;
}
return pNode;
}
void reversed(LinkList* L) {
if (size(L) == 0)
{
return;
}
reversedAtNode(L, *L);
}
void main() {
Lnode* head = NULL;
initSingleLinkList(head);
for (int i = 0; i < 5; i++)
{
headInsert(&head, i);
}
show(head);
for (int i = 5; i < 10; i++)
{
tailInsert(&head, i);
}
show(head);
//判断链表中是否包含元素e
if (contains(head, 3)) {
printf("包含元素%d\n", 3);
}
else
{
printf("不包含元素%d\n", 3);
}
//删除第一次出现在链表中的元素为e的节点
printf("测试删除==========\n");
delete(head, 3);
show(head);
//删除链表中第index的元素,返回数据与
printf("测试删除第index的节点==========\n");
int resDel;
deleteIndex(&head, 8, &resDel);
printf("被删除的是%d\n", resDel);
show(head);
//测试链表的逆转
printf("测试链表的逆转=======\n");
show(head);
printf("=================start\n");
reversed(&head);
show(head);
}