#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool InitList(LinkList&L){//初始化一个空的单链表 ,不带头节点
L=NULL;//空表,此时没有任何节点,防止脏数据
return true;
}
bool InitList2(LinkList&L){//带头节点
L=(LNode*)malloc(sizeof(LNode));//分配一个头节点
if (L==NULL)//内存不足,分配失败
return false;
L->next=NULL;//头节点之后暂时没有节点
return true;
}
/*单链表的插入和删除*/
//在第i个位置插入元素e(带头节点)
/*好处:
1.第一个数据节点的位置被存放在头节点的指针域里,因此在链表的第一个位置上的操作和在表的其他位置的操作一致
2.无论链表是否为空,其头指针都指向头节点的非空指针
*/
bool ListInsert(LinkList&L,int i,ElemType e){
if(i<1)
return false;
LNode*p;//p指向当前扫描到的节点
int j=0;//p指向的是第几个节点
p=L;//L指向头节点,头节点设定为第0个节点
while(p!=NULL&&j<i-1){//循环找到第i-1个节点
p=p->next;
j++;
}
if(p==NULL)//i的值不合法
return false;
LNode*s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
//不带头节点
bool ListInsert2(LinkList&L,int i,ElemType e){
if(i<1)
return false;
if(i==1){
//插入第一个节点的操作不同
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s;//头指针指向新的节点
return true;
}
LNode*p;//p指向当前扫描到的节点
int j=1;//p指向的是第几个节点
p=L;//L指向头节点,头节点设定为第0个节点
while(p!=NULL&&j<i-1){//循环找到第i-1个节点
p=p->next;
j++;
}
if(p==NULL)//i的值不合法
return false;
LNode*s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;//插入成功
}
/*在p结点之后插入元素e*/
bool InsertNextNode(LNode*p,ElemType e){
if (p==NULL)
return false;
LNode*s=(LNode*)malloc(sizeof(LNode));
if(s==NULL)//内存分配失败
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
/*在p节点之前插入元素e*让e成为p的后继节点是可以操作的,然后把两个表中的数据域互换*/
bool InsertPriorNode(LNode*p,ElemType e) {
if(p==NULL)
return false;
LNode *s=(LNode*)malloc(sizeof(LNode));
if (s==NULL)
return false;
s->next=p->next;
p->next=s;
s->data=p->data;//把数据做一个交换
p->data=e;
}
/*带头节点的删除某一位置i 的元素*/
bool ListDelete(LinkList&L,int i,ElemType&e){
if(i<1)
return false;
LNode*p;
int j=0;
p=L;
while (p!=NULL && j<i-1){//和插入一样的操作,为了找到第i-1个节点
p=p->next;
j++;
}
if(p==NULL)//i值不合法
return false;
if(p->next==NULL)//要删除的节点是空
return false;
LNode*q=p->next;/*让一个指针q指向要被删除的节点*///
e=q->data;//返回元素值
p->next=q->next;//让*q元素从列表中断开
free(q);
return true;
}
/*删除指定节点p*/
bool DeleteNode(LNode*p){
/*类似于后插,p不能是最后一个元素*/
/*单链表不能逆向检索--双链表*/
if(p==NULL)
return false;
LNode*q=p->next;//q指向p所指向元素的后继
p->data=p->next->data; //把p的数据域换成后继的数据域,还差个next没换,next指向*p的next指向即可,然后把q所指向的地址free掉
p->next=q->next;
free(q);
return true;
}
/*按位查找,返回第i个元素,带头节点,设其为0*/
LNode*GetElem(LinkList L,int i){
if(i<0)
return NULL;
LNode*p;//p指向当前扫描到的节点
int j=0;//p指向的是第几个节点
p=L;//L指向头节点,头节点设定为第0个节点
while(p!=NULL&&j<i){//循环找到第i个节点
p=p->next;
j++;
}
}
/*按值查找,找到数值为e 的节点*/
LNode *LocateElem(LinkList L,ElemType e){
LNode *p=L->next;
//从第一个节点开始查找,如果是struct类型,我们就需要额外写一个函数依次比较里面的元素
while(p!=NULL&&p->data!=e)
p=p->next;
return p;
}
/*求表长*/
int length(LinkList L){
int len=0;
LNode *p=L;
while(p->next!=NULL){
p=p->next;
len++;
}
return len;
}
/*尾插法建立单链表*/
LinkList List_TailInsert(LinkList&L){//正向建立单链表
int x;
L=(LinkList)malloc(sizeof(LNode));
LNode*s,*r=L;//r为表尾指针
scanf("%d",&x);
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode));//在头节点之后创建一个新的节点
s->data=x;//数据域
r->next=s;//节点之间连接
r=s;//r指向尾节点
scanf("%d",&x);
}
r->next=NULL;
return L;
}
/*头插法建立单链表--调用后插操作--链表的逆置(把新的节点插入到表头后面)*/
LinkList List_HeadInsert(LinkList&L){
//逆向建立单链表,按照输入元素的逆序进行输出构造链表
LNode *s;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;//重要,防止NULL指向未知的地址,受脏数据的影响
scanf("%d",&x);
while(x!=9999)
{
s=(LNode*)malloc(sizeof(LNode));//创建新的节点,实际上就是后插操作
s->data=x;
s->next=L->next;
L->next=s;
}
}
数据结构(单链表的笔记和方法)
最新推荐文章于 2022-11-25 09:36:56 发布
这篇博客详细介绍了如何在C语言中实现带头节点和不带头节点的单链表初始化、插入元素以及删除元素的操作。包括在指定位置插入、删除节点的功能,以及按值和位置查找节点的方法。此外,还提供了头插法和尾插法建立单链表的示例代码。
摘要由CSDN通过智能技术生成