自己参考了一些书和网上的代码,然后总结了一下。附加一些自己在途中遇见的错误。可以运行,可以通过。
代码实现
#include <stdio.h>
#include <stdlib.h>
typedef enum {
false,true} Status;
typedef struct
{
char *name;
}ElemType;
typedef struct Node
{
ElemType data;
struct Node *Next;
}Node;
typedef struct Node *LinkList;
Status InitList(LinkList *L);
Status ListAdd(LinkList L,ElemType e);
void ShowList(LinkList L);
Status ListInsert(LinkList L,int i,ElemType e);
Status ListDeleteNo(LinkList L,int i);
Status GetElem(LinkList L, int i,LinkList *e);
int getlength(LinkList L);
int main()
{
printf("构造链表: \n");
LinkList test ;
InitList(&test);
ElemType one = {
"郭龙"};
ElemType two = {
"陈宁"};
ElemType three = {
"石翔旭"};
ElemType four = {
"许可"};
ElemType five = {
"庄钦"};
ElemType six = {
"刘沛沛"};
ListAdd(test,one);
ListAdd(test,two);
ListAdd(test,three);
ListAdd(test,four);
ListAdd(test,five);
ListAdd(test,six);
ShowList(test);
printf("4号位插入节点: \n");
ElemType insert = {
"吴天爬"};
ListInsert(test,4,insert);
ShowList(test);
printf("6号删除结点:\n");
ListDeleteNo(test,6);
ShowList(test);
printf("查找3号结点,并将之删除返回 \n \n");
LinkList goal;
GetElem(test,2,&goal);
printf("查找的目标节点:%s \n\n",goal->data.name);
printf("查找之后的链表: \n");
ShowList(test);
printf("测试:获取链表的长度 \n \n");
int length = 0;
printf("链表的长度为:%d \n",getlength(test));
ShowList(test);
return 0;
}
Status InitList(LinkList *L)
{
*L = (Node *)malloc(sizeof(Node));
if(*L == NULL)
{
printf("申请空间失败");
return false;
}
(*L)->Next = NULL;
return true;
}
Status ListAdd(LinkList L,ElemType e)
{
Node *temp;
temp = (Node *)malloc(sizeof(Node));
if(temp == NULL)
{
printf("分配失败");
return false;
}
temp->data = e;
temp->Next = NULL;
while(L->Next)
{
L = L->Next;
}
L->Next = temp;
return true;
}
Status ListInsert(LinkList L,int i,ElemType e)
{
if(!L->Next )
{
printf("链表为空");
return false;
}
if(i < 1)
{
printf("输入非法");
return false;
}
LinkList p = NULL;
p = L->Next;
int j = 1;
while(p && j < i - 1)
{
p = p->Next;
j ++;
}
if(!p )
{
return false;
}
Node *temp = NULL;
temp = (Node *)malloc(sizeof(Node));
if(!temp)
{
printf("未申请到空间");
return false;
}
temp->data = e;
temp->Next = NULL;
temp->Next = p->Next;
p->Next = temp;
return true;
}
Status ListDeleteNo(LinkList L,int i)
{
if(!L->Next || i < 1)
{
return false;
}
LinkList p = NULL;
p = L->Next;
int j = 1;
while(p && j < i - 1)
{
p = p->Next;
j ++;
}
if(!p)
{
return false;
}
LinkList q = NULL;
q = p->Next;
p->Next = p->Next->Next;
free(q);
return true;
}
Status GetElem(LinkList L,int i,LinkList *e)
{
if(i < 1 || !L->Next)
{
return false;
}
int j = 1;
L = L->Next;
while(L && j < i)
{
L = L->Next;
j ++;
}
if(!L)
{
return false;
}
*e = L;
return true;
}
int getlength(LinkList L)
{
int j = 0;
L = L->Next;
while(L)
{
L = L->Next;
j ++;
}
return j;
}
void ShowList(LinkList L)
{
L = L->Next;
int i = 1;
while(L)
{
printf(" 结点%3d:%5s \n",i,L->data.name);
i ++;
L = L->Next;
}
printf("*********************************************************** \n \n");
}
运行效果
常见错误一:尾结点的Next指针并没有处理
- 没有将加入的最后一个结点的指针域next置为NULL,陷入无限的死循环
常见的错误二:初始化函数InitList
Status InitList(LinkList L)
{
L = (Node *)malloc(sizeof(Node));
if(L == NULL)
{
printf("申请空间失败");
return false;
}
L->Next = NULL;
return true;
}
- 错误分析:传入的是在主函数声明的指向结点的指针,但是在函数中自己又申请了新的地址,改变了形参的值。已经和主函数声明的指针没有任何关系。所以,并没有初始化成功。
- 将指针当做链表本身,以为改了指针就是改了链表本身。实际形参的指针的值,并没有改变实参。
常见错误三:混淆指针和指针的指针的含义
- 在主函数中将一个指针初始化为NULL,通过值传递,传递给函数。在函数中对形参进行解引用操作,指向的仍旧是NULL,即使对NULL进行赋值还是NULL。
- 要想改变主函数中的指针值,应该调用主函数中指针的指针,通过指针的指针来改变主函数中指针的指向的具体的地址值。
- 改正方法一:在主函数中构造一个具体的结构体,在函数中通过指针将主函数中的结构体值改变
- 改正方法二:将函数的形参改为指针的指针,通过函数将链表对应的结点的地址传递给主函数的指针。
- 问题:由于已经链表的结点的地址传递出来了,就有从外界非法改动链表的可能,所以不建议采用
常见错误四:删除或者清空整个链表,没有的将对应的结点的内存释放
- 删除结点或者清空整个链表,记得回收对应的空间。否则会造成内存泄露,可用的内存空间越来越少。