头文件 MyList.h
#ifndef _MYLIST_H_
#define _MYLIST_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct Node;
typedef struct Node *pNode;
struct Head;
typedef struct Head *pHead;
pHead Create (void); // 初始化头节点
int GetLength (pHead pH); // 获得链表长度
bool IsEmpty (pHead pH); // 判断链表是否为空
void Insert (pHead pH, int pos, int val); // 插入元素
pNode Delete (pHead pH, int val); // 删除链表中的元素
pNode Search (pHead pH, int val); // 查找元素
void Destory (pHead pH); // 销毁链表
void PrintFront (pHead pH); // 顺序打印链表
void PrintReverse (pHead pH); // 逆序打印链表
struct Head
{
int length; // 记录链表长度
pNode next;
};
struct Node
{
int data;
pNode pre; // 指向前一个节点,前驱指针
pNode next; // 只想后一个节点,后继指针
};
pHead
Create (void)
{
pHead pH = (pHead)malloc (sizeof (struct Head));
if (pH == NULL)
{
printf ("Error Create!");
exit (1);
}
pH -> length = 0;
pH -> next = NULL;
return pH;
}
int
GetLengh (pHead pH)
{
if (pH == NULL)
{
printf ("Error Head!");
exit (1);
}
return pH -> length;
}
bool
IsEmpty (pHead pH)
{
if (pH == NULL)
{
printf ("Error Head!");
exit (1);
}
if (pH -> length == 0)
{
return true;
}
return false;
}
void
Insert (pHead pH, int pos, int val)
{
if (pH == NULL || pos < 0 || pos > pH -> length)
{
printf ("Error Input!");
exit (1);
}
pNode p = (pNode)malloc (sizeof (struct Node));
if (p == NULL)
{
printf ("Error Memory!");
exit (1);
}
p -> data = val; // 将 val 保存在新节点数据域中
if (IsEmpty (pH)) // 链表为空
{
pH -> next = p; // 将头节点与新节点链接
p -> pre = NULL;
p -> next = NULL;
}
else
{
pNode pCur = pH -> next; // 头节点的下一个节点
if (pos == 0) // 在头节点后插入
{
pH -> next = p; // 将头节点与新节点链接
p -> pre = NULL;
p -> next = pCur; // 将新节点与原头节点后的节点相连接
pCur -> pre = p; // 将原节点前驱指针指向新节点
}
else // 不是第一个位置
{
for (int i = 1; i < pos; i ++)
{
pCur = pCur -> next; // 遍历找到插入位置
}
// 结束后pCur指向要插入位置的节点
p -> next = pCur -> next; // 将新节点与当前节点的下一节点链接
pCur -> next -> pre = p; // 将当前节点的下一节点前驱指针指向新节点
p -> pre = pCur; // 将新节点的前驱指针指向当前节点
pCur -> next = p; // 将当前节点与新节点链接
}
}
pH -> length ++; // 长度加 1
}
pNode
Delete (pHead pH, int val)
{
if (pH == NULL || pH -> length == 0)
{
printf ("Error Head!");
exit (1);
}
pNode p = Search (pH, val); // 通过 Search 函数找到该节点
if (p == NULL)
{
printf ("Error input!");
return NULL;
}
pNode pPre = p -> pre;
pNode pNext = p -> next;
// 将删除节点的前后节点相链接
pNext -> pre = pPre;
pPre -> next = pNext;
printf ("成功删除!\n");
return p;
}
pNode
Search (pHead pH, int val)
{
if (pH == NULL)
{
printf ("Error Head!");
}
pNode p = pH -> next;
do
{
if (p -> data == val)
{
return p;
}
p = p -> next;
}
while (p -> next != NULL);
printf ("Not Found!\n");
return NULL;
}
void
Destory (pHead pH)
{
pNode pCur = pH -> next;
pNode p = NULL;
if (pH == NULL)
{
printf ("Error Head!");
}
while (pCur -> next != NULL)
{
p = pCur -> next; // 通过 p 来传递节点地址
free (pCur); // 释放该节点
pCur = p;
}
pH -> length = 0; // 回到初始化
pH -> next = NULL;
}
void
PrintFront (pHead pH)
{
if (pH == NULL)
{
printf ("Error Head!");
}
pNode p = pH -> next;
while (p != NULL)
{
printf ("%d ", p -> data);
p = p -> next;
}
printf ("\n");
}
void
PrintReverse (pHead pH)
{
if (pH == NULL)
{
printf ("Error Head!");
}
pNode p = pH ->next;
while (p -> next != NULL) // 先遍历至链表末尾
{
p = p -> next;
}
int len = pH -> length;
for (int i = len - 1; i >= 0; i --) // 从后向前打印
{
printf ("%d ", p -> data);
p = p -> pre;
}
printf ("\n");
}
#endif // _MYLIST_H_
测试文件 main.c
#include "../../MyHeader/MyList.h"
/**@Author Ivan Lee **/
int main(void)
{
pHead pH = NULL;
pH = Create (); // 创建双链表
int num;
printf ("请输入要插入的元素, 输入-1结束 \n");
while (1)
{
scanf ("%d", &num);
if (num == -1)
{
break;
}
Insert (pH, 0, num);
}
printf ("当前双链表长度: %d \n", GetLengh (pH));
printf ("顺序打印链表: \n");
PrintFront (pH);
printf ("逆序打印链表: \n");
PrintReverse (pH);
int target;
printf ("请输入要查找的元素: ");
scanf ("%d", &target);
Search (pH, target);
int del;
printf ("请输入要删除的元素: ");
scanf ("%d", &del);
Delete (pH, del);
printf ("删除后链表元素: \n");
PrintFront (pH);
Destory (pH);
printf ("成功销毁!\n");
printf ("当前链表长度为 %d \n", pH -> length);
system ("pause");
return 0;
}
PS 采用的头插法,因此非常义上的顺序逆序输出