代码是初学者边学边写,一则记录成长历程,二则希望能给像我一样的初学者带来点滴帮助,如有错误欢迎指正;
C语言描述;
只带尾指针的循环单向链表算法;
何为循环单向链表看数据结构书?这里不做介绍,只给代码;
包含:创建空表,销毁,清空,插入,删除,判断是否为空表,返回表的长度,得到第i个结点的值,得到表中第一个等于e的结点的位置,合并两个链表;
/*注意点:
1,可能改变谁是尾结点的操作,函数形参需是原变量
2,可能改变谁是尾结点的操作,末尾勿忘更改尾指针
3,练习题
* 在空表中正序插入5个结点
* 对上述5个结点非递增排序 */
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
} LNode;
typedef LNode* LinkList;
//创建空表:尾指针指向头结点,头结点的指针域指向自己
void InitList(LinkList* L)
{
*L = (LNode*)malloc(sizeof(LNode));
if(!*L) exit(-1);
(*L)->next = *L;
}
bool DestroyList(LinkList* L)
{//注意循环链表,p的开始状态要和判断状态中间隔一个结点
//因为对于循环链表,开始p指向头结点,而循环条件是p不指向头结点
LNode* q;
LNode* p = (*L)->next;//p指向头结点
while(p!=*L)//到倒二结点
{
q = p->next;
free(p);
p = q;
}
free(*L);//此处是坑!!!释放最后一个结点
*L = NULL;
return true;
}
bool ClearList(LinkList *L)
{//可能改变谁是最后一个结点的函数形参设置成LNode**L;
LNode* p,* q;
p = (*L)->next->next;
while(p!=(*L)->next)
{
q = p->next;
free(p);
p = q;
}
*L = p;
p->next = p;
return true;
}
bool EmptyList(LinkList L)
{
return L->next==L?true:false;
}
int LengthList(LinkList L)
{
int j = 0;
LNode* p = L->next;
while(p!=L)
{
j++;
p = p->next;
}
return j;
}
bool GetElem(LinkList L,int i,ElemType* e)
{
if(i<1||i>LengthList(L))
{
printf("i的值不合理\n");
return false;
}
LNode* p = L->next;
for(int j=0;j<i;j++)
p=p->next;
*e = p->data;
return true;
}
int LocateElem(LinkList L,ElemType e)
{
int j = 1;
LNode* p = L->next->next;//p指向首元结点
while(p!=L->next)//p到尾结点后结束
{
if(p->data==e)
return j;
j++;
p=p->next;
}
return 0;
}
//在第i个位置前插入值为e的新结点:i值可以是length+1
bool InsertList(LinkList* L,int i,ElemType e)
{
if(i<1||i>LengthList(*L)+1)
return false;//i值是否合理
LNode* p = (*L)->next;
for(int j=0;j<i-1;j++)
{
p = p->next;
}
LNode* New = (LNode*)malloc(sizeof(LNode));//构建新结点
if(!New) return false;
New->data = e;
New->next = p->next;
p->next = New;//插入结束
if(p==*L)//如果新结点是最后一个结点
*L = New;//更改尾指针
return true;
}
//删除链表第i个结点,被删除结点的值返回给e
bool DeleteList(LinkList* L,int i,ElemType* e)
{
if(i<1||i>LengthList(*L))
return false;//i值是否合理
LNode* p = (*L)->next;
for(int j=0;j<i-1;j++)
p = p->next;
LNode* q;
q = p->next;//先保存被删除结点的地址留着释放
*e = q->data;//被删除结点的值返回给e
p->next = q->next;//删除结点
if(q==*L)//如果被删除结点是最后一个结点
*L = p;//改变尾指针为倒数第二个结点
free(q);//释放被删除的结点
return true;
}
//在单向循环链表中寻找第一个与e相等的结点的位置
void TraverseList(LinkList L)
{
LNode* p = L->next->next;
while(p!=L->next)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
//合并Lb到La中:La和Lb均是只有尾指针的单向循环链表
void MergeList(LinkList* La,LinkList Lb)
{
(*La)->next = Lb->next->next;//La尾结点接Lb首元结点
free(Lb->next);//释放Lb头结点
Lb->next = (*La)->next;//Lb尾结点接La头结点
*La = Lb;//更改La的尾指针
}
int main()
{
LinkList L;
ElemType e;
int j;
InitList(&L); /* 初始化单循环链表L */
EmptyList(L);
if(!InsertList(&L,1,3)) /* 在L中依次插入3,5 */
printf("i的值不合理\n");
else
printf("在第1个结点前插入3\n");
if(!InsertList(&L,2,5))
printf("i的值不合理\n");
else
printf("在第2个结点前插入5\n");
if(!InsertList(&L,2,7))
printf("i的值不合理\n");
else
printf("在第2个结点前插入7\n");
GetElem(L,1,&e);
printf("L中数据元素个数=%d,第1个元素的值为%d。\n",LengthList(L),e);
printf("L中的数据元素依次为:");
TraverseList(L);
j = LocateElem(L,4);
if(j)
printf("L的第%d个元素为4。\n",j);
else
printf("没有与4相等的结点\n");
j = LocateElem(L,5);
if(j)
printf("L的第%d个元素为5。\n",j);
else
printf("没有与5相等的结点\n");
if(!DeleteList(&L,1,&e))
printf("i的值不合理!\n");
else
printf("删除了第1个结点%d\n",e);
printf("删除第1个结点后遍历链表:\n");
TraverseList(L);
printf("清空L:%d(1: 成功)\n",ClearList(&L));
printf("清空L后,L是否空:%d(1:空 0:否)\n",EmptyList(L));
printf("销毁L:%d(1: 成功)\n",DestroyList(&L));
}