数据结构之循环链表实现

数据结构

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

typedef int ElemType;

typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

//循环链表初始化
LNode* init_list();
//函数返回值是头结点地址

//在链表的第ii位置插入元素ee
int Insert_Elem(LNode * LL,unsigned int ii,ElemType* ee);

//打印整个链表数值
void printlinklist(LNode * LL);

//计算整个链表的长度
int  LengthList(LinkList LL);

//判断链表是否为空
int IsEmpty(LinkList LL);

// 获取链表中第ii个结点,成功返回结点的地址,失败返回空。
// 注意,ii可以取值为0,表示头结点。
LNode *LocateNode(LinkList LL, unsigned int ii);

// 查找元素ee在链表LL中的结点地址,如果没找到返回NULL,否则返回结点的地址。
LNode *LocateElem(LinkList LL, ElemType *ee);


// 在指定结点pp之后插入元素ee,返回值:0-失败;1-成功。
int InsertNextNode(LNode *pp, ElemType *ee);

// 在指定结点pp之前插入元素ee,返回值:0-失败;1-成功。
int InsertPriorNode(LNode *pp, ElemType *ee);

void main()
{
	int i=0;
	ElemType ee;
	LinkList LL=init_list();
	//在初始化循环链表之后使用这样的赋值其实
	//和pp=pp->next作用是一样的,这是因为只有一个头结点
	LNode* pp=LL->next;

	printf("判断链表是否为空\n");
	printf("%d\n",IsEmpty(LL));

	printf("LL=%p\n",LL);
	printf("在表中插入元素1,2,3,4,5,6,7,8,9\n");

	for(i=1;i<10;i++)
	{
		ee=i;
		Insert_Elem(LL,i,&ee);
	}

	printf("打印链表的全部数值\n");
	printlinklist(LL);
	pp=pp->next;
	pp=pp->next;
	ee=15;InsertPriorNode(pp,&ee);
	printf("打印链表的全部数值\n");
	printlinklist(LL);

	printf("判断链表是否为空\n");
	printf("%d\n",IsEmpty(LL));

	printf("打印链表的全部数值\n");
	printlinklist(LL);

	printf("计算链表的长度\n");
	printf("链表的长度为 %d \n",LengthList(LL));

	//获取第5个元素的地址
	pp=LocateNode(LL,5);
	//显示第五个元素的数值为
	printf("第5个元素的数值为%d\n",pp->next);

	//查找元素0的位置,这个时候没有插入元素0
	ee=0;LocateElem(LL,&ee);

	//插入元素0
	ee=0;InsertNextNode(LL,&ee);


	//对应元素位置节点查找
	LocateElem(NULL,&ee);
	ee=0;LocateElem(LL,&ee);
	ee=1;LocateElem(LL,&ee);
	ee=2;LocateElem(LL,&ee);
	ee=3;LocateElem(LL,&ee);
	ee=4;LocateElem(LL,&ee);
	ee=5;LocateElem(LL,&ee);
	ee=6;LocateElem(LL,&ee);
	ee=7;LocateElem(LL,&ee);
	ee=8;LocateElem(LL,&ee);
	ee=9;LocateElem(LL,&ee);

	ee=10;LocateElem(LL,&ee);

	printf("打印链表的全部数值\n");
	printlinklist(LL);
	pp=pp->next;
	ee=15;InsertPriorNode(pp,&ee);
	printf("打印链表的全部数值\n");
	printlinklist(LL);

	system("pause");
}

//循环链表初始化
LNode* init_list()
{
	//定义头结点为一个LNode*类型的指针,并且分配给他LNode类型大小的内存
	LNode* head=(LNode*)malloc(sizeof(LNode));

	//如果分配内存失败,那么malloc()返回的就是一个空指针
	if(head==NULL) 
	{
		printf("内存空间不足");
		return NULL;
	}

	head->next=head;//头节点的指针指向自己

	//返回头结点地址
	return head;

	//这样说来头结点好像没有元素,那我可不可以自己给他添加一个元素呢
	//打印一下试试
	//-842150451
	//如果直接打印他的值就是上面的数值
	//试试给他赋值
	//赋值可以正常赋值
}

//插入数值函数 返回0插入成功,返回1插入失败
int Insert_Elem(LinkList LL,unsigned int ii,ElemType* ee)
{
	//这款编辑器只支持在开头定义变量
	//要不然会报非法的错误
	unsigned int kk=1;
	LNode* pp=NULL;
	LNode* tem=(LNode*)malloc(sizeof(LNode));

	if(LL==NULL || ee==NULL){printf("链表或者元素为空");return 0;}

	if(ii<1) {printf("插入位置不合法,应该ii>=1");return 0;}


	if(ii==1)
	{
		pp=LL;
	}
	else
	{
		pp=LL->next;//这里不能直接写成pp=pp->next 因为这个时候pp连初始值都没有
		//如果这里写的是pp=pp->next;
		//pp没有赋值为NULL的时候这个窗口会直接消失
		//pp赋值为NULL的时候会多停留一会
		//主要原因是这样pp的值指向不明确
		//然后崩溃了
		while(pp!=LL && kk<ii-1)
		{
			pp=pp->next;
			kk++;
		}
		if(pp==LL){printf("插入位置超过表长");return 0;}
	}

	if(tem==NULL){printf("内存空间不足");return 0;}

	tem->data=*ee;

	//指针处理
	tem->next=pp->next;
	pp->next=tem;

	return 1;
}

//打印所有数值的函数
void printlinklist(LNode * LL)
{
	LNode* pp=LL;

	pp=pp->next;
	while(pp!=LL) {printf("  %d  ",pp->data); pp=pp->next;}
}

//销毁链表
void DestroyList1(LinkList LL)
{
	LNode *head=LL;
	LNode *tem=NULL;
	LL=LL->next;
	while(tem!=LL)
	{
		tem=LL->next;
		free(tem);
		LL=tem;
	}

	free(head);

	return;
}


// 求链表的长度,返回值:>=0-表LL结点的个数
int  LengthList(LinkList LL)
{
	LNode* pp=LL;
	int length=0;

	//从有数据的节点开始计算
	pp=pp->next;

	while(pp!=LL){length++; pp=pp->next;}

	return length;

	//不使用临时变量来计算链表的长度
	//这个方法理论上是没有问题的,但是在这里不能正确的使用
	//我觉得应该是编译器的问题
	//这里用的是VS2010
	//if(LL==NULL)
	//	return 0;
	//else
	//	return LengthList(LL->next)+1;

	  // 不使用临时变量,如何计算链表(包括头结点)的长度?
   //if (LL==NULL) return 0;
   //return LengthList(LL->next)+1;
}

// 判断链表是否为空,返回值:0-非空或失败,1-空。
int IsEmpty(LinkList LL)
{
	if(LL==NULL) return 0;
	if(LL->next==LL) return 1;
	return 0;
}

// 获取链表中第ii个结点,成功返回结点的地址,失败返回空。
// 注意,ii可以取值为0,表示头结点。
LNode *LocateNode(LinkList LL, unsigned int ii)
{
	unsigned int i=0;
	LNode* pp=LL;

	if(LL==NULL) {printf("链表为空");return NULL;}

	for(i=0;i<ii;i++)
	{
		pp=pp->next;
		if(pp==LL){printf("位置超过表长"); return NULL;}
	}

	printf("从头结点开始算起,第%d个节点地址为%p\n",ii,pp);
	return pp;
}

// 查找元素ee在链表LL中的结点地址,如果没找到返回NULL,否则返回结点的地址。
LNode *LocateElem(LinkList LL, ElemType *ee)
{
	LNode* pp=LL;
	if(LL==NULL){printf("链表为空\n"); return NULL;}
	pp=pp->next;

	while(pp!=LL)//循环链表,循环到头节点时代表当前的链表已经遍历
	{
		if(pp->data==*ee){printf("找到元素地址 %p \n",pp); return pp;}
		pp=pp->next;
	}

	printf("没有找到链表之中对应的元素\n");
	return NULL;
}


// 在指定结点pp之后插入元素ee,返回值:0-失败;1-成功。
int InsertNextNode(LNode *pp, ElemType *ee)
{
	LNode * newlnode=(LNode*)malloc(sizeof(struct LNode));
	if(pp==NULL){printf("节点为空无法插入\n"); return 0;}
	//对新生节点赋值
	newlnode->data=*ee;
	
	//节点插入到当前之后
	newlnode->next=pp->next;
	pp->next=newlnode;

	printf("节点插入成功\n");
	printf("节点地址为 %p \n",newlnode);
	return 1;
}

// 在指定结点pp之前插入元素ee,返回值:0-失败;1-成功。
int InsertPriorNode(LNode *pp, ElemType *ee)
{
	LNode * tem=(LNode*)malloc(sizeof(struct LNode));
	if(pp==NULL){printf("节点为空无法插入\n"); return 0;}
	if(tem==NULL){printf("新的节点创建失败\n"); return 0;}

	//节点插入操作
	//把pp节点的元素的和指针赋值到tme中
	memcpy(&tem->data,&pp->data,sizeof(ElemType));
	tem->next=pp->next;

	//对tem节点赋值
	pp->data=*ee;
	pp->next=tem;

	printf("前向节点插入成功\n");
	return 1;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值