循环链表的建立(带头结点)


一、基本思路

1.循环链表与单链表的区别

(1)初始化的时候,头结点的next指向它自己;

(2)判断条件上,由p!=NULL更换为p != *L;

(3)更新尾结点的时候,要由NULL改为*L;

二、代码如下


/*
          项目名称:循环链表的建立与基本操作

		  编译环境:VC++ 2008
		  
		  作者相关:。。。
		  
		  最后修改:2019.5.31


          学习目标:1.掌握循环链表的基本操作
		   
		            2.利用头指针实现的循环链表

          注意事项:1.测试所有功能是否正常




*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define OK    1
#define ERROR 0
#define TRUE  1
#define FALSE 0

typedef int   ElemType;
typedef bool  Status;



//定义链表结点结构体
typedef struct Node
{
    ElemType data;
	struct Node *next;

}Node,*LinkList;



//函数声明
Status InitList( LinkList *L );

Status ListEmpty( LinkList L );

Status ClearList( LinkList *L );

int    LengthList( LinkList L );

int    LocateElem( LinkList L, ElemType e );

Status GetElem( LinkList L, int i, ElemType *e );

Status ListInsert( LinkList *L, int i, ElemType e );

void   CreateListHead( LinkList *L, int n );//头插法

void   CreateListTail( LinkList *L, int n );//尾插法

Status ListDelete( LinkList *L, int i, ElemType *e );

Status   OutList( LinkList L );



int main()
{
    LinkList L1,L2,L3;

    if(InitList(&L1))
		printf("L1已被初始化!\n\n");

	if(ListEmpty(L1))
		printf("L1为空!\n\n");

	for(int i=1;i<=10;i++)
	    ListInsert(&L1,1,i);
	OutList(L1);
   
	printf("循环链表的长度是%d \n\n",LengthList(L1));
 
	if(!ListEmpty(L1))
	{
	    int k = LocateElem(L1,7);
	    printf("循环链表中元素7的位置是%d\n\n",k);
        LocateElem(L1,11);

	    GetElem(L1,3,&k);
		printf("循环链表中第3个元素是%d\n\n",k);

		ListDelete(&L1,9,&k);
		printf("删除第9个元素%d后,",k);
		OutList(L1);
	}
	else
	    printf("循环链表是空的!\n\n");
        
	ClearList(&L1);
	printf("清空链表后:");
    if(ListEmpty(L1))
		printf("L1为空!\n\n");

    CreateListHead(&L2,10);
	printf("头插法创建,");
	OutList(L2);

    CreateListTail(&L3,10);
	printf("尾插法创建,");
	OutList(L3);

	return 0;
}


//初始化,建立头结点,L指向此头结点
Status InitList( LinkList *L )
{
    *L = (LinkList)malloc(sizeof(Node));//头结点是LinkList类型
	if(!L)
		return ERROR;
	(*L)->next = *L;//头结点的next指向它自己

	return OK;
}

Status ListEmpty( LinkList L )
{
    if(L->next != L)
		return FALSE;
    else
		return TRUE;
}

//清空链表:只保留头结点
Status ClearList( LinkList *L )
{
    LinkList p,q;

	p = (*L)->next;//p指向第一个结点
    while(p!=*L)
	{
	    q = p->next;
		free(p);//释放p所指向结点的内存
		p = q;//p再指向下一个结点
	}

	(*L)->next = *L;

	return OK;
}


int    LengthList( LinkList L )
{
    LinkList p;
	int count = 0;

	p=L->next;//p指向第一个结点

	while(p!=L)
	{
	    ++count;
		p = p->next;
	}

	return count;
}


//返回链表中与e相等元素的位置,没有则返回0
int    LocateElem( LinkList L, ElemType e )
{
    if(ListEmpty(L))
	{
	    printf("循环链表是空的!\n\n");
		return ERROR;
	}

	LinkList p;
	int i=1;

	p = L->next;//p指向第一个结点
	while(p!=L)
	{
	    if(p->data == e)
			return i;
		else
		{
		    p=p->next;
			++i;
		}
	}

	if(p == L)
	{
	    printf("循环链表里与%d相等的元素不存在!\n\n",e);
		return 0;
	}
}


//用e返回链表中第i个数据元素的值
Status GetElem( LinkList L, int i, ElemType *e )
{
	LinkList p;
	int j = 1;
	p = L->next;

	while(p!=L&&j<i)//算法思想:工作指针后移
	{
	    p=p->next;
		++j;
	}

	if(p==L||j>i)
        return ERROR;

	*e = p->data;
	return OK;
}


//在第i个元素之前插入数据e
Status ListInsert( LinkList *L, int i, ElemType e )
{    
	LinkList p,s;

	int j = 1;

	p = *L;

	if( i<1 ||i>LengthList(*L)+1)
	{
	    printf("i 的值非法!\n\n");
	}

	while(j<i)
	{
		p=p->next;
		++j;
	}

	s=(LinkList)malloc(sizeof(Node));
	s->data = e;
	s->next = p->next; 
	p->next = s;

	return OK;

}


//随机产生n个数,利用头插法完成链表的''整表创建''
void   CreateListHead( LinkList *L, int n )
{
    LinkList p;
	*L = (LinkList)malloc(sizeof(Node));
    (*L)->next = *L;

	srand(time(0));//随时间产生不同的随机数种子

	for(int i=0;i<n;i++)
	{
	    p = (LinkList)malloc(sizeof(Node));
		p->data = rand()%100+1;//任何数对100取余是0~99,进而取值范围是1~100
		p->next = (*L)->next;
		(*L)->next = p;
	}
}

//随机产生n个数,利用尾插法完成链表的''整表创建''
void   CreateListTail( LinkList *L, int n )
{
    LinkList p,s;//p指向尾结点
	*L = (LinkList)malloc(sizeof(Node));

	srand(time(0));
	p = *L;

	for(int i=0;i<n;i++)
	{
	    s = (LinkList)malloc(sizeof(Node));
		s->data = rand()%100+1;
		p->next = s;
		p = s;//更新p的位置到尾结点
	}
	p->next = *L;
}

//删除链表中第i个数据元素
Status ListDelete( LinkList *L, int i, ElemType *e )
{
    LinkList p,q;
	int j=1;
	p = *L;

    while(p->next!=(*L)&&j<i)//p有后继结点并且j<i
	{
		p=p->next;
		++j;
	}

	if(p==*L||j>i)//i的值不存在
	{
		return ERROR;
    }
    
	q = p->next;
    p->next = q->next;

	*e = q->data;
    free(q);

	return OK;

}



Status   OutList( LinkList L )
{
    LinkList p;
	p=L->next;

	printf("循环链表内容如下: \n\n");
	while(p!=L)
	{
	    printf("%d ",p->data);
		p=p->next;
	    
	}
    printf("\n\n");
	return OK;
}

三、效果

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值