typedef struct Lnode
{ ElemType data; /*数据域,保存结点的值 */
struct Lnode *next; /*指针域*/
}LNode; /*结点的类型 */
1 建立单链表
⑴ 头插入法建表
LNode *create_LinkList(void)
/* 头插入法创建单链表,链表的头结点head作为返回值 */
{
int data ;
LNode *head, *p;
head= (LNode *) malloc( sizeof(LNode));
head->next=NULL; /* 创建链表的表头结点head */
while (1)
{
scanf(“%d”, &data) ;
if (data==32767) break ;
p= (LNode *)malloc(sizeof(LNode));
p–>data=data; /* 数据域赋值 */
p–>next=head–>next ;
head–>next=p ;
/* 钩链,新创建的结点总是作为第一个结点 */
}
return (head);
}
(2) 尾插入法建表
LNode *create_LinkList(void)
/* 尾插入法创建单链表,链表的头结点head作为返回值 */
{
int data ;
LNode *head, *p, *q;
head=p=(LNode *)malloc(sizeof(LNode));
p->next=NULL; /* 创建单链表的表头结点head */
while (1)
{
scanf(“%d”,& data);
if (data==32767) break ;
q= (LNode *)malloc(sizeof(LNode));
q–>data=data; /* 数据域赋值 */
q–>next=p–>next;
p–>next=q;
p=q ;
/*钩链,新创建的结点总是作为最后一个结点*/
}
return (head);
}
2 单链表的查找
(1) 按序号查找 取单链表中的第i个元素
ElemType Get_Elem(LNode *L , int i)
{
int j ;
LNode *p;
p=L->next; /* 使p指向第一个结点 */
j=1;
while (p!=NULL && j<i)
{
p=p–>next;
j++;
} /* 移动指针p , j计数 */
if (j!=i) return(-32768) ;
else return(p->data);
/* p为NULL 表示i太大; j>i表示i为0 */
}
(2) 按值查找
LNode *Locate_Node(LNode *L,int key)
/* 在以L为头结点的单链表中查找值为key的第一个结点 */
{
LNode *p=L–>next;
while ( p!=NULL&& p–>data!=key) p=p–>next;
if (p–>data==key) return p;
else
{
printf(“所要查找的结点不存在!!\n”);
retutn(NULL);
}
}
3 单链表的插入
插入运算是将值为e的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。
void Insert_LNode(LNode *L,int i,ElemType e)
/* 在以L为头结点的单链表的第i个位置插入值为e的结点 */
{
int j=0;
LNode *p,*q;
p=L–>next ;
while ( p!=NULL&& j<i-1)
{
p=p–>next;
j++;
}
if (j!=i-1) printf(“i太大或i为0!!\n ”);
else
{
q=(LNode *)malloc(sizeof(LNode));
q–>data=e;
q–>next=p–>next;
p–>next=q;
}
}
4 单链表的删除
⑴ 按序号删除
删除单链表中的第i个结点。
void Delete_LinkList(LNode *L, int i)
/* 删除以L为头结点的单链表中的第i个结点 */
{
int j=1;
LNode *p,*q;
p=L;
q=L->next;
while ( p->next!=NULL && j<i)
{
p=q;
q=q–>next;
j++;
}
if (j!=i) printf(“i太大或i为0!!\n ”);
else
{
p–>next=q–>next;
free(q);
}
}
⑵ 按值删除
删除单链表中值为key的第一个结点。
void Delete_LinkList(LNode *L,int key)
/* 删除以L为头结点的单链表中值为key的第一个结点 */
{
LNode *p=L, *q=L–>next;
while ( q!=NULL&& q–>data!=key)
{
p=q;
q=q–>next;
}
if (q–>data==key)
{
p->next=q->next;
free(q);
}
else printf(“所要删除的结点不存在!!\n”);
}
变形之一:
删除单链表中值为key的所有结点。
void Delete_LinkList_Node(LNode *L,int key)
{
LNode *p=L, *q=L–>next;
while ( q!=NULL)
{
if (q–>data==key)
{
p->next=q->next;
free(q);
q=p->next;
}
else
{
p=q;
q=q–>next;
}
}
}
变形之二:
删除单链表中所有值重复的结点,使得所有结点的值都不相同。
void Delete_Node_value(LNode *L)
/* 删除以L为头结点的单链表中所有值相同的结点 */
{
LNode *p=L->next, *q, *ptr;
while ( p!=NULL) /* 检查链表中所有结点 */
{
q=p, ptr=p–>next;
/* 检查结点p的所有后继结点ptr */
while (ptr!=NULL)
{
if (ptr–>data==p->data)
{
q->next=ptr->next;
free(ptr);
ptr=q->next;
}
else
{
q=ptr;
ptr=ptr–>next;
}
}
p=p->next ;
}
}
5 单链表的合并
设有两个有序的单链表,它们的头指针分别是La 、 Lb,将它们合并为以Lc为头指针的有序链表。
算法说明:算法中pa ,pb分别是待考察的两个链表的当前结点,pc是合并过程中合并的链表的最后一个结点。
LNode *Merge_LinkList(LNode *La, LNode *Lb)
/* 合并以La, Lb为头结点的两个有序单链表 */
{
LNode *Lc, *pa , *pb , *pc, *ptr ;
Lc=La ;
pc=La ;
pa=La->next ;
pb=Lb->next ;
while (pa!=NULL && pb!=NULL)
{
if (pa->data<pb->data)
{
pc->next=pa ;
pc=pa ;
pa=pa->next ;
}
/* 将pa所指的结点合并,pa指向下一个结点 */
if (pa->data>pb->data)
{
pc->next=pb ;
pc=pb ;
pb=pb->next ;
}
/* 将pa所指的结点合并,pa指向下一个结点 */
if (pa->data==pb->data)
{
pc->next=pa ;
pc=pa ;
pa=pa->next ;
ptr=pb ;
pb=pb->next ;
free(ptr) ;
}
/* 将pa所指的结点合并,pb所指结点删除 */
}
if (pa!=NULL) pc->next=pa ;
else pc->next=pb ; /*将剩余的结点链上*/
free(Lb) ;
return(Lc) ;
}
循环链表
⑴ 判断是否是空链表:head->next==head ;
⑵ 判断是否是表尾结点:p->next==head ;
双向链表
1 双向链表的结点及其类型定义
typedef struct Dulnode
{ ElemType data ;
struct Dulnode *prior , *next ;
}DulNode ;
(1) 双向链表的插入 将值为e的结点插入双向链表中。
① 插入时仅仅指出直接前驱结点,钩链时必须注意先后次序是: “先右后左” 。部分语句组如下:
S=(DulNode *)malloc(sizeof(DulNode));
S->data=e;
S->next=p->next; p->next->prior=S;
p->next=S; S->prior=p; /* 钩链次序非常重要 */
② 插入时同时指出直接前驱结点p和直接后继结点q,钩链时无须注意先后次序。部分语句组如下:
S=(DulNode *)malloc(sizeof(DulNode));
S->data=e;
p->next=S; S->next=q;
S->prior=p; q->prior=S;
(2) 双向链表的结点删除
设要删除的结点为p ,删除时可以不引入新的辅助指针变量,可以直接先断链,再释放结点。部分语句组如下:
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);