#include<stdio.h>
#include<stdlib.h> //malloc、free函数的头文件
typedef int ElemType;
typedef struct LNode{ //定义单链表结点类型
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList;//使用LNode *强调这是一个结点;使用LinkList强调这是一个单链表
//1.初始化一个单链表(带头结点)
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode)); //分配一个结点
if(L==NULL) //内存不足,分配失败
return false;
L->next = NULL;
return true; //头结点之后暂时还没有结点
}
//2.采用头插法建立单链表
LinkList List_HeadInsert(LinkList &L){ //逆向建立单链表
LNode *s; //这里声明一个结点s说明后面肯定要为它分配空间
int x;
L = (LinkList)malloc(sizeof(L)); //创建头结点
L->next = NULL; //初始为空链表
printf("请输入链表:(当输入9999是结束输入)\n");
scanf("%d",&x); //输入结点的值
while(x!=9999){ //输入9999表示结束
s = (LNode *)malloc(sizeof(LNode)); //创建新结点
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d",&x);
}
return L;
}
//3.采用尾插法建立单链表
LinkList List_TailInsert(LinkList &L){ //正向建立单链表
int x; //设元素x为整型
L = (LNode *)malloc(sizeof(LNode)); //创建头结点
LNode *s,*r = L; //r为表尾指针
printf("请输入链表:\n");
scanf("%d",&x); //输入结点的值
while(x!=9999){ //输入9999表示结束
s = (LNode *)malloc(sizeof(LNode)); //创建新结点
s->data = x;
r->next = s;
r = s; //r指向新的表尾结点
scanf("%d",&x); //继续输入
}
r->next = NULL; //尾结点指针置空
return L;
}
//4.在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList &L,int i,int 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)); //创建一个新结点存储元素e
s->data = e;
//在p的后面插入s
s->next = p->next;
p->next = s; //将s连到p的后面
return true; //插入成功
}
//5.删除第i个结点,并把值带回
bool ListDelete(LinkList &L,int i,int &e){ //&e为了把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;
if(p->next == NULL) //第i-1个结点后已无其它结点
return false;
LNode *q = p->next; //用q指向被删除结点
e= q->data;
p->next = q->next; //将*q从链中“断开”
free(q); //释放结点的存储空间
return true; //删除成功
}
//6.按位查找,返回第i个元素(带头结点)
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++;
}
return p; //返回第i个结点,若i大于表长,则返回NULL
}
//7.后插操作:在p结点后插入元素e
bool InsertNextNode(LNode *p,int e){
if(p==NULL) //i值不合法(超出单链表长度)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode)); //创建一个新结点存储元素e
s->data = e;
//在p的后面插入s
s->next = p->next;
p->next = s; //将s连到p的后面
return true; //插入成功
}
//8.按值查找表结点
LNode *LocateElem(LinkList L,int e){
LNode *p = L->next;
while(p!=NULL&&p->data!=e){ //从第1个结点开始查找data域为e的结点
p = p->next;
return p; //找到后返回该结点指针,否则返回NULL
}
}
//9.对某一结点进行前插操作
bool InsertPriorNode(LinkList L,int i,int e){
LNode *p = GetElem(L,i-1); //找到第i-1个结点
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode)); //创建新结点存e的值
if(s==NULL)
return false; //内存分配失败
s->next = p->next;
p->next = s; //将新结点s连到p之后
s->data = p->data; //将p中的元素复制到s中
p->data = e; //p中的元素赋值为e
return true;
}
//10.对某一结点进行删除操作
bool DeleteNode(LinkList L,int i){
LNode *p = GetElem(L,i); //找到第i个结点
if(p==NULL)
return false;
LNode *q = p->next; //令q指向*p的后继结点
p->data = p->next->data;//用后继结点的数据域覆盖p(如果p是最后一个结点,这里会出错)
p->next = q->next; //将*q结点从链中“断开”
free(q); //释放后继结点的存储空间
return true;
}
//11.求表长操作
int Length(LinkList L){
int len = 0; //统计表长
LNode *p = L->next; //指针p指向第一个结点
while(p!=NULL){
p = p->next;
len++;
}
return len;
}
//12.打印单链表
void PrintList(LinkList L) {
LinkList p; //创建一个指针p
p = L->next; //p指向第一个结点
printf("链表为:\n");
while (p != NULL) { //判断p是否为空
printf("%d ", p->data); //依次输入p的数据
p = p->next; //指针p每循环一次指向下一个结点元素
}
printf("\n");
}
int main(){
LinkList L;
InitList(L);
List_HeadInsert(L);
PrintList(L);
return 0;
}
带头结点单链表相关操作
这篇文章详细介绍了如何使用C语言创建和操作单链表,包括初始化、头插法和尾插法建立链表、在指定位置插入和删除元素、获取元素、查找操作以及打印链表。代码示例涵盖了链表数据结构的基础操作。
摘要由CSDN通过智能技术生成