原文链接
单链表
单链表是由一个个结点构成的,上一个结点指向下一个结点的位置。与顺序表不同,单链表的结点除了存储数据元素外,还有一个指针域,用来指示下一个节点的位置。根据这一特性,虽然单链表多储存了一个指针域,存储密度没有顺序表大,但是更加灵活,多少个数据就创建多少个结点。
根据链表结点所含指针的个数,指针指向和指针连接方式,可将链表分成单链表,循环链表,双向链表,二叉链表,十字链表,邻接表,邻接多重表。其中,这里只简单介绍单链表。
LNode 和 LinkList
对于LNode和LinkList,可能大家不太了解这两个作用,也可能看到这样定义一个结构体很奇怪。首先大家要先了解一下struct结构体的基本用法,我在这一篇博客专门说了这个问题,大家可以看一下。
C语言struct简述
总的来说,在书中的这个例子中,LNode为这个结构体的一个变量,而LinkList为指向这个结构体的指针类型。相当于 struct LNode LNode 和struct LNode* LinkList。其中Lnode *p
中的p和LinkList L
中的L是一样,都是指向结构体Lnode的指针变量,这里是为了让LinkList L特意指向头节点,与其他普通的节点分开,才特意多设置一个LinkList指针类型。
在后边的代码中,L一直指向的就是头结点。而LNode *p就是创建了一个新的结点。
头结点
关于头结点,首元结点,头指针的概念,书中说的很清楚了,这里就不过多赘述。
对于下文的代码,为带有有头结点的单链表代码。设置头结点的好处有很多,书上也介绍了,就不多说废话。
其中,LinkList L
创建的就是头指针,并且L一直指向的就是头结点。L->next指向的才是第一个元素的数据,也就是首元结点。初试化的时候L->next=NULL。
初始化
对于书中的初始化单链表代码,用到了引用。按照c语言没办法这样写。
我是这样写这个函数的,虽然看着有点奇怪,但是没办法。
LinkList L;
L = (LNode *)malloc(sizeof(LNode));
InitList(L);
int InitList(LinkList L)
{
L->next =NULL;
return OK;
}
只能这样写,如果把L = (LNode *)malloc(sizeof(LNode));
这条语句写在InitList函数里面,就会出现错误。虽然不报错,但是会产生大问题。我当时就在这被坑了好久。
具体不能这样写的原因是,你把L指针传到InitList中,然后再函数里面使用malloc函数。你就把L指向的地址改变了,然后函数里面的L指针是一个局部变量,没办法影响到外边的L指针,所以相当于这个函数没用。
其他地方
其他地方就没有什么可说的了。除了书上的给的函数,我还自己写了几个可能会用到的函数,算是补充吧。
完整代码
#include
#include
#define OK 1
#define ERROR -1
typedef struct
{
float coef;
int expn;
}Polynomial;
typedef struct LNode
{
Polynomial data;
struct LNode *next;
}LNode, *LinkList;
//初始化函数
int InitList(LinkList L);
//获取第i个结点的数据
int GetElem(LinkList L, int i,Polynomial *e);
//获取结点数据为e的结点地址
LNode *LocateElem(LinkList L,Polynomial e);
//在i位置插入结点e
int ListInsert(LinkList L, int i, Polynomial e);
//遍历整个单链表,输出每个单链表的值
int TraverseList(LinkList L);
//删除第i个结点
int ListDelete(LinkList L,int i);
//前插法建立单链表
int CreateList_H(LinkList L,int n);
//后插法建立单链表
int CreateList_R(LinkList L,int n);
//获取结点值为cur_e的前面那个结点的值,并存储在pre_e中
int PriorElem(LinkList L,Polynomial cur_e,Polynomial *pre_e);
//获取结点值为cur_e的后面那个结点的值,并存储在next_e中
int NextElem(LinkList L,Polynomial cur_e,Polynomial *next_e);
//将两个有序线性表按指数从小到大组合到L3单链表中
int margc(LinkList L1,LinkList L2,LinkList L3);
int i,j,k;
int main()
{
int status;
LinkList L;
//重要提醒,这一条语句只能放到函数外边
L = (LNode *)malloc(sizeof(LNode));
InitList(L);
Polynomial e;
int d;
float f;
i=0;
/* //利用ListInsert创建一个单链表
while(scanf("%d %f %d",&d,&f,&i)&&(d!=-1&&f!=-1))
{
e.coef = f;
e.expn = d;
status = ListInsert(L, i, e);
}
TraverseList(L);
*/
/*
scanf("%d",&i);
CreateList_H(L,i);
TraverseList(L);
*/
/*
scanf("%d",&i);
CreateList_R(L,i);
TraverseList(L);
*/
/*
scanf("%d",&i);
GetElem(L,i,&e);
printf("%d %f\n",e.expn,e.coef);
*/
/*
scanf("%d %f",&d,&f);
e.coef=f;
e.expn=d;
LNode *p;
p = LocateElem(L,e);
printf("%p\n",p);
*/
/*
scanf("%d",&i);
ListDelete(L,i);
TraverseList(L);
*/
/*
Polynomial cur_e,pre_e;
scanf("%d %f",&cur_e.expn,&cur_e.coef);
PriorElem(L,cur_e,&pre_e);
printf("%d %f\n",pre_e.expn,pre_e.coef);
*/
/*
Polynomial cur_e,next_e;
scanf("%d %f",&cur_e.expn,&cur_e.coef);
NextElem(L,cur_e,&next_e);
printf("%d %f\n",next_e.expn,next_e.coef);
*/
/* //验证margc函数
LinkList L1,L2,L3;
L1 = (LNode *)malloc(sizeof(LNode));
L2 = (LNode *)malloc(sizeof(LNode));
L3 = (LNode *)malloc(sizeof(LNode));
InitList(L1);
InitList(L2);
InitList(L3);
while(scanf("%d %f %d",&d,&f,&i)&&(d!=-1&&f!=-1))
{
e.coef = f;
e.expn = d;
status = ListInsert(L1, i, e);
}
TraverseList(L1);
while(scanf("%d %f %d",&d,&f,&i)&&(d!=-1&&f!=-1))
{
e.coef = f;
e.expn = d;
status = ListInsert(L2, i, e);
}
TraverseList(L2);
margc(L1,L2,L3);
TraverseList(L3);
*/
return 0;
}
int InitList(LinkList L)
{
L->next =NULL;
return OK;
}
int GetElem(LinkList L, int i,Polynomial *e)
{
LNode *p;
p = L->next;
j=1;
while(p&&jnext;
j++;
}
if(!p||j>i)
return ERROR;
e->coef=p->data.coef;
e->expn = p->data.coef;
return OK;
}
LNode *LocateElem(LinkList L,Polynomial e)
{
LNode *p;
p=L->next;
while((p->data.coef!=e.coef || p->data.expn!= e.expn)&&p)
p->next;
return p;
}
int ListInsert(LinkList L, int i, Polynomial e)
{
LNode *p;
p = L;
j=0;
while(p && (jnext;
j++;
}
if(!p && j>i-1)
return ERROR;
LNode *s;
s = (LNode *)malloc(sizeof(LNode));
s->data.coef = e.coef;
s->data.expn = e.expn;
s->next = p->next;
p->next = s;
return OK;
}
int TraverseList(LinkList L)
{
LNode *p;
p = L->next;
while(p)
{
printf("%d %f\n",p->data.expn,p->data.coef);
p=p->next;
}
}
int ListDelete(LinkList L,int i)
{
LNode *p;
p = L;
j = 0;
while((p->next) && (jnext;
j++;
}
if(!(p->next) || j>i-1)
return ERROR;
LNode *q;
q=p->next;
p->next = q->next;
free(q);
return OK;
}
int CreateList_H(LinkList L,int n)
{
LNode *p;
for(i=0;idata.expn,&p->data.coef);
p->next=L->next;
L->next = p;
}
}
int CreateList_R(LinkList L,int n)
{
LNode *p;
LNode *r;
r=L;
for(i=0;idata.expn,&p->data.coef);
p->next=NULL;
r->next = p;
r=p;
}
}
int PriorElem(LinkList L,Polynomial cur_e,Polynomial *pre_e)
{
LNode *p;
LNode *pre;
p=L->next;
pre = NULL;
while(p&&(p->data.coef!=cur_e.coef&&p->data.expn!=cur_e.expn))
{
pre = p;
p=p->next;
}
if(!pre)
return ERROR;
pre_e->coef = pre->data.coef;
pre_e->expn = pre->data.expn;
return OK;
}
int NextElem(LinkList L,Polynomial cur_e,Polynomial *next_e)
{
LNode *p;
LNode *next;
p=L->next;
next = NULL;
while(p&&(p->data.coef!=cur_e.coef&&p->data.expn!=cur_e.expn))
{
p=p->next;
next=p->next;
}
if(!next)
return ERROR;
next_e->coef = next->data.coef;
next_e->expn = next->data.expn;
return OK;
}
int margc(LinkList L1,LinkList L2,LinkList L3)
{
LNode *p;
LNode *l1,*l2;
l1=L1->next;
l2 = L2->next;
p=L3;
while(l1&&l2)
{
if(l1->data.expn<=l2->data.expn)
{
p->next= l1;
l1=l1->next;
}
else
{
p->next = l2;
l2=l2->next;
}
p=p->next;
}
while(l1)
{
p->next=l1;
l1 = l1->next;
p=p->next;
}
while(l2)
{
p->next=l2;
l2=l2->next;
p=p->next;
}
return OK;
}