以下是我加过注释后的代码,望同学们易读好学,有改进之处可以提出来!有错误之处也望大神指出!
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int
typedef struct LNode
{
int data; //存放当前数据的数据内容
struct LNode *next; //存放下个数据的地址
}LNode,*LinkList;
//用LNode来代替struct LNode这句声明。
//首先, 在复杂的程序里,很容易打错一些字,比如把struct打成stuct,把struct LNode 打成struct LNdoe blablabla~,用typedef可以避免这种错误发生。
//其次, 简单省事,struct LNode *head; 和 LNode *head;都是定义头节点的作用,但显然后者更加便捷。(当然不怕麻烦并且足够自信的话用第一个也完全没问题)
int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
LinkList p,q;
//LinkList L只改变结构体的内容,不改变L的地址
//LinkList *L会改变L的地址
int i;
ElemType e;
L = (LinkList)malloc(sizeof(LNode));//生成新结点作为头结点,即L为头结点
//动态内存申请样例:如p = (int *)malloc(sizeof(int));
L->next = NULL; // 给头结点下一个结点接上NULL,以NULL隔开,让头结点成为旧结点
q = (LinkList)malloc(sizeof(LNode));//给予新结点q内存空间
q = L;//新结点q变成旧结点(为下一个新结点的生成铺垫条件,即q结点为null后的结点)
for (i=0; i<n; i++)
{ //生成n个元素的单链表
scanf("%d", &e);
p = (LinkList)malloc(sizeof(LNode)); // 给新节点p分配空间
p -> data = e; //把e赋给结点p的数据域
p -> next = NULL; //新节点指向空,因为后面还没有元素加入
q -> next = p; //旧结点的指针指向新节点 把新旧结点链接起来
q = p; //把新结点p变为旧结点q,为新的结点加入而做铺垫
}
return OK;
}
int LoadLink_L(LinkList &L){
// 单链表遍历并输出数据
LinkList p = L->next;
if(p==NULL)
printf("The List is empty!");
else
{
printf("The LinkList is:");
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;//指针下移
}
}
printf("\n");
return OK;
}
int LinkInsert_L(LinkList &L,int i,ElemType e){
// 算法2.9
// 在带头结点的单链线性表L中第i个位置之前插入元素e
// 请补全代码
LNode * newNode = (LinkList)malloc(sizeof(LNode)); //定义新节点newNode并赋予内存,LNode为定义新节点
newNode->data=e;//将e值放入newNode结点中
newNode->next=NULL;//给newNode接上一个为空的新结点
int num=0;//记录链表有多少个结点
LNode * p = L->next;//头节点的下一个结点位置定义为结点p
while(p!=NULL)//p非空时
{
p=p->next;//指向p的下一个结点
num++;//结点数+1
}
if(i>num+1)//当输入的第i个位置超出了链表长度时
{
return ERROR;//返回ERROR值
}
p= L;//将p定位为头节点
int j=0;
while(j<i-1&&p!=NULL) //查找第i-1个结点,p指向该结点
{
p=p->next;
j++;
}
newNode->next=p->next;//将i-1结点的下一个位置(即i)赋给新结点的下一个位置
p->next=newNode;//将新结点放入i-1结点的下一个位置(即i)
return OK;
}
int LinkDelete_L(LinkList &L,int i, ElemType &e){
// 算法2.10
// 在带头结点的单链线性表L中,删除第i个元素,并用e返回其值
// 请补全代码
int num=0;//记录链表有多少个节点
LNode * p=L->next;//新结点p为表头的下一个节点
while(p!=NULL)//p非空时,统计总共多少个结点
{
p=p->next;
num++;
}
if(i>num||i==0)//如果输入的i大于结点数或者i的位置为0
{
return ERROR;
}
p=L;//将指针p的位置移动到L
int j=0;
while(j<i-1&&p!=NULL)//查找第i-1个结点,p指向该结点
{
p=p->next;
j++;
}
e=p->next->data;//记录要被删除的节点数据
LNode * temp =p->next;//新建一个temp结点记录p->next的地址
p->next=p->next->next;//越过将要删除的temp结点,将链表连起来,为删除temp做准备
free(temp); //删除temp
return OK;
}
int main()
{
LinkList T;
int a,n,i;
ElemType x, e;
printf("Please input the init size of the linklist:\n");
scanf("%d",&n);
printf("Please input the %d element of the linklist:\n", n);
if(CreateLink_L(T,n)) // 判断链表是否创建成功,请填空
{
printf("A Link List Has Created.\n");
LoadLink_L(T);
}
while(1)
{
printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d%d",&i,&x);
if(!LinkInsert_L(T,i,x)) printf("Insert Error!\n"); // 判断i值是否合法,请填空
else printf("The Element %d is Successfully Inserted!\n", x);
break;
case 2: scanf("%d",&i);
if( !LinkDelete_L(T,i,e)) printf("Delete Error!\n"); // 判断i值是否合法,请填空
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3: LoadLink_L(T);
break;
case 0: return 1;
}
}
}
本文详细介绍了单链表的基本操作,包括创建、遍历、插入和删除等核心功能的实现方法,并提供了完整的C语言代码示例及注释,有助于读者理解和掌握单链表的使用。
1040

被折叠的 条评论
为什么被折叠?



