**
总结一下链表常用操作,写的不是很好,有需要朋友看看,注释按自己理解注明了
/*有头节点的链表(头节点无数据)
* @Description: 链表的 1.建立(头插,尾插)2.输出第n个节点 3.删除第n个节点,并保存值 4.插入元素到第n个节点 5.删除所哟节点 6.输出所有节点
* @Version: 1.0
* @Author: BaiYiZhuo
* @Date: 2020-11-21 17:31:36
* @LastEditTime: 2020-11-21 22:59:58
*/
//bool为布尔类型 true or false 返回值即o or 1
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct LNode //定义单链表结点类型
{
ElemType data;
struct LNode *next; //指向后继结点
} LinkList;
LinkList * CreateListF(LinkList *L,ElemType a[],int n);//头插法建立单链表。
LinkList * CreateListR(LinkList *L,ElemType a[],int n);//尾插法建立单链表。
void DispListN(LinkList *L,int n); //输出第n个结点值。 n为结点的逻辑序号。如果n不在链表长度范围,则输出结点值用NULL表示。
bool ListInsert(LinkList *&L,int i,ElemType e); //将元素e插入在L的第i个结点处,i为结点的逻辑序号,i的取值在【1,L->Length+1】范围内时,可成功插入,返回true, 否则插入失败,返回false
void DispList(LinkList *L); //输出单链表所有结点值,每个结点之间用空格间隔,如果链表为空,则输出NULL。全部输出用换行符结束。
void SetListNULL(LinkList *L);//删除链表所有数据结点,将链表置为空表。 裁判程序实现。
void DispList(LinkList *L); //输出链表所有结点值。每个结点之间用空格间隔,全部输出用换行结束。 如果链表为空,则输出NULL。
bool ListDelete(LinkList *&L,int i,ElemType &e); //删除L的第i个结点,将删除的结点值保存在e,i为结点的逻辑序号,i的取值在【1,L->Length】范围内时,可成功删除,返回true, 否则删除失败,返回false。
int main()
{
LinkList *L;//建立一个指向链表元素的指针变量
/*自定*/
return 0;
}
//头插法建立链表
LinkList * CreateListF(LinkList *L,ElemType a[],int n)
{
L=(LinkList*)malloc(sizeof(LinkList));//为链表指针L申请指向链表类型的地址
L->next=NULL;//初始化 头节点next置空
for(int i=0;i<n;i++)//节点中输入n个元素
{
LinkList *pnew;
pnew=(LinkList*)malloc(sizeof(LinkList));
pnew->data=a[i];
pnew->next=L->next;//L(HEAD)->节点1->节点2->节点3(让新节点指向原head节点指向的值)
L->next=pnew;//刷新头节点指向
}
return L;
}
//尾插法建立单链表
LinkList * CreateListR(LinkList *L,ElemType a[],int n)
{
L=(LinkList*)malloc(sizeof(LinkList));//为链表指针L申请指向链表类型的地址
L->next=NULL;//初始化 头节点next置空
LinkList *rear;//尾节点
rear=L;//尾节点等于头节点
for(int i=0;i<n;i++)//节点中输入n个元素
{
LinkList *pnew;//新节点
pnew=(LinkList*)malloc(sizeof(LinkList));
pnew->data=a[i];//新节点赋值
pnew->next=NULL;//新节点置空
rear->next=pnew;//原来尾节点指针指向新节点
rear=pnew;//更新尾节点
}
return L;
}
//输出所有节点值
void DispList(LinkList *L)
{
if(!L->next) //判断存的 ***第一个元素****是否存在!
printf("NULL");
else
{
LinkList* p;
p=L->next;
while(p)//元素非空
{
printf("%c ",p->data);
p=p->next;
}
}
printf("\n");
}
//置空链表
void SetListNULL(LinkList *L)
{
LinkList *headelement,*temp;//临时指针变量和存头节点指针变量
headelement=L->next;//赋值为第一个元素地址
while(headelement!=NULL)//判断存元素的headelement是否存着元素
{
temp=headelement->next;//保存下一元素位置
free(headelement);//释放当前位置元素空间
headelement=temp;//刷新当前值
}
L->next=NULL;//循环结束置空头指针
return;
}
//将元素e插入在L的第i个结点处
bool ListInsert(LinkList *&L ,int i ,ElemType e)
{
LinkList *in,*pre;//插入节点in 前驱节点pre
pre=L;
int j=0;
while(pre&&j<i-1)//找到i所在的前驱位置,即1.pre首先不为空避免空链表 2.确定j的前驱位置
{
pre=pre->next;
j++;
}
if(!pre||i<=0)//判断找到的位置是否超出链表边界(插入位置大于1 或者 链表长度+1)!pre(前驱等于零的时候即插入位置在长度加2的位置)
return false;
in=(LinkList*)malloc(sizeof(LinkList));
in->data=e;
in->next=pre->next;//新插入元素的下一个元素指向待插入位置前驱指向的下一个元素(即指向待插入位置的下一个元素)
pre->next=in;//前驱元素指针指向新元素
return true;
}
//输出第n个元素
void DispListN(LinkList *L,int n)
{
LinkList *pre;
pre=L;
int j=0;
while(pre&&j<n-1)//找第n个元素的前驱元素
{
pre=pre->next;
j++;
}
if(!pre||n<=0)//判断找到的元素位置是否在链表范围内
printf("The %dth is NULL",n);
else
printf("The %dth is %c",n,pre->next->data);//输出前驱元素的下一个元素中的数据(即当前元素位置数据)
return;
}
//删除第i位元素的值,并保存在e中(地址传递)
bool ListDelete(LinkList*&L,int i,ElemType &e)
{
LinkList *p,*temp=NULL;//初始化指针 ***置空***防止野指针!
p=L;
int j=0;
while(p&&j<i-1)//找第i个元素的前驱元素
{
p=p->next;
j++;
}
if(!p||i<=0)//判断找到的元素位置是否在链表范围内
return false;
temp=p->next;//保存当前节点位置
p->next=temp->next;//前驱节点指向当前节点的下一个元素
e=temp->data;//取出当前去掉节点的值到e
free(temp);//释放已删除节点
return true;
}
//遍历节点
void DispList(LinkList *L)
{
LinkList *p;
p=L->next;//从有元素的开始读
if(!p)//没元素
printf("NULL");
while(p)//有元素
{
printf("%c ",p->data);
p=p->next;
}
printf("\n");
return;
}