注意:L可以表示为头指针或是头结点,L->next可以表示为头结点的下一个结点
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
typedef int ElemType;
//定义一个链表
typedef struct LNode
{
ElemType data;//结点的数据域
struct LNode* next;//结点的指针域
}LNode, * LinkList;
bool InitList(LinkList L);//初始化链表
LNode* GetElem(LinkList L, int i);//按位查找
LNode* LocateElem(LinkList L, ElemType e);//按值查找
bool ListInsert(LinkList L, int i, ElemType e);//按位序插入
bool InsertNextNode(LNode* p, ElemType e);//指定结点的后插操作
bool InsertPriorNode(LNode* p, ElemType e);//指定结点的前插操作
bool ListDelete(LinkList L, int i, ElemType e);//按位序删除
bool DeleteNode(LNode* p);//删除指定结点
int length(LinkList L);//求链表表长
LinkList List_Taillnsert(LinkList L);//用尾插法建立单链表
bool PrintList(LinkList L);//打印链表的元素
bool InitList(LinkList L)//初始化链表
{
printf("********初始化单链表********\n");
L = (LinkList)malloc(sizeof(LNode));//生成新结点作为头结点,用头指针L指向头结点
L->next = NULL;//头结点的指针域置空
if (L->next == NULL)
{
printf("链表初始化成功!\n");
}
else printf("链表初始化失败!\n");
return true;
//system("pause");//暂停,不然控制台程序会一闪即过,你来不及看到执行结果
//system("cls");
}
LNode* GetElem(LinkList L, int i)//按位查找
{
if (i < 0)
{
printf("输入的位置不合法\n");
}
LNode* p;
int j = 0;
p = L;
while (p != NULL && j < i)
{
p = p->next;
j++;
}
return p;
}
LNode* LocateElem(LinkList L, ElemType e)//按值查找
{
LNode* p = L->next;
while (p != NULL && p->data != e)
{
p = p->next;
}
return p;
}
bool ListInsert(LinkList L, int i, ElemType e)//按位序插入
{
if (i < 1)
{
printf("输入的位置不合法\n");
}
//LNode* p;//当前指针指向的结点
//int j = 0;//当前指针指向的是第几个结点,0表示指向头结点
//p = L;
//while(p != NULL && j < i - 1)//循环找到第i-1个结点
//{
// p = p->next;
// j++;
//}
LNode* p = GetElem(L, i - 1); //封装
/*if(p==NULL)
printf("输入的位置不合法\n");
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
printf("插入成功\n");*/
return InsertNextNode(p, e); //这里就发挥了封装的作用,使函数简化了
}
bool InsertNextNode(LNode* p, ElemType e)//指定结点的后插操作
{
if (p == NULL)
{
printf("输入的结点不合法\n");
}
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
printf("申请新结点失败\n");
s->data = e;
s->next = p->next;
p->next = s;
printf("插入结点成功\n");
}
bool InsertPriorNode(LNode* p, ElemType e)//指定结点的前插操作
{
if (p == NULL)
printf("输入的结点不合法\n");
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
printf("该结点的内存分配失败\n");
s->data = p->data;
s->next = p->next;
p->next = s;
p->data = e;
printf("插入结点成功\n");
}
bool ListDelete(LinkList L, int i, ElemType e)//按位序删除
{
if(i<1)
{
printf("输入的位置不合法\n");
}
/*LNode* p;
int j = 0;
p = L;
while (p != NULL && j < i - 1)
{
p = p->next;
j++;
}*/
LNode* p = GetElem(L, i - 1); //再次使用封装
if (p == NULL)
{
printf("输入的位置不合法\n");
}
if (p->next == NULL)
{
printf("该结点为空,删除失败\n");
}
LNode* q = p->next;//令q指向被删除结点
e = q->data;
p->next = q->next;
free(q);
printf("删除结点成功,该节点的元素是%d", e);
}
bool DeleteNode(LNode* p)//删除指定结点
{
if (p == NULL)
printf("输入的结点为空,删除失败\n");
LNode* q = p->next;
p->data = q->data;
p->next = q->next;
free(q);
printf("删除结点成功\n");
} //若p是单链表的最后一个结点,q会出现空指针的错误,则只能引入头结点,依次循环找到p的前一个结点
int length(LinkList L) //求链表表长
{
int len = 0;
LNode* p = L;
while (p->next != NULL)
{
p = p->next;
len++;
}
return len;
}
LinkList List_Taillnsert(LinkList L)//用尾插法建立单链表
{
int len = 0;
LNode* q = L;
int x;
printf("请输入要插入元素的个数:");
scanf("%d", &x);
for(int i = 0;i < x ; i++)
{
printf("请输入要插入的值:");
int num;
scanf("%d", &num);
InsertNextNode(q, num);
}
return L;
}
bool PrintList(LinkList L)//打印链表的元素
{
LNode* p;
p = L->next;
while (p)//直到最后一个结点后停止
{
printf("%d ", p->data);
p = p->next;//使p指向下一个结点
}
printf("\n");
}