数据结构之线性表(1-2)——单链表(带头节点)的基本操作

7 篇文章 1 订阅
5 篇文章 0 订阅

1 结构体定义

//定义data成员的类型
typedef int ElementType;
//定义单链表节点类型
typedef struct LNode
{
	ElementType data;
	struct LNode *next;
}LinkList;

2 动作

// 初始化单链表(创建头节点)
LinkList* InitList(LinkList *&L);
//获取单链表长度(长度不包括头节点)
int ListLength(LinkList *L);
bool isListEmpty(LinkList *L);
// 清空单链表 ,L->next=NULL
void ClearList(LinkList *&L);
//尾插法从数组中插入节点到单链表
LinkList* ToilInsert(LinkList *&L,ElementType e[],int n);
//遍历单链表
void DispList(LinkList *L);
//返回给定元素值对应节点的下标位置
int LinkListLocate(LinkList *L,ElementType x);
//返回指定下标的链表节点元素值
ElementType elementAt(LinkList *L,int index);
// 在指定元素值x对应的节点后插入元素值为e的节点(头插)
int insertNode(LinkList *&L,ElementType x,ElementType e);
//从键盘输入节点信息,构造单链表(尾插法)
LinkList* LinkListCreate( );
//销毁单链表(包含头节点在内),回收节点空间
void DestList(LinkList *&L);//删除节点之前,存储该节点的后继节点信息
/* 从单链表中删除某给定元素对应的节点 */
void LinkListDel(LinkList *&L,ElementType x);

3 代码

//指向第一个节点的指针叫头指针
//头节点是方便操作而设定的节点,其data变量一般不设置值。但也有可能存储哨兵或者链表的长度
#include<stdio.h>
#include<stdlib.h>
//定义data成员的类型
typedef int ElementType;
//定义单链表节点类型
typedef struct LNode
{
	ElementType data;
	struct LNode *next;
}LinkList;

//初始化单链表——创建头指针
LinkList* InitList(LinkList *&L)
{
	//只有一个头节点,该节点的data为空,但有地址和内存空间
	if(L==NULL)
	{
		//分配空间
		L=(LinkList*)malloc(sizeof(LinkList));
		//更新指针成员
		L->next=NULL;
		printf("初始化成功!\n");
	}
	else
		printf("已经初始化过了!\n");
	return L;
}

//判断链表是否为空——根据ListLength() 判断
bool isListEmpty(LinkList *L)
{
	return ListLength(L)>0?0:1;
}

//清空单链表——头指针的next成员指向NULL
void ClearList(LinkList *&L)
{
	//当头指针存在时,将L的成员变量指向NULL
	if(L!=NULL)
		L->next=NULL;
	printf("清空成功!\n");
}

//单链表长度
int ListLength(LinkList *L)
{
	//长度计数器——一定要初始化
	int i=0;
	//头指针存在时
	if(L!=NULL)
	{
		LinkList *p=0;
		p=L->next;
		
		while(p!=NULL)//先得保证p不为空,p->next才有意义
		{
			i++;
			p=p->next;
		}
		p=0;
		free(0);
	}
	return i;
}
//尾插法插入元素——尾巴后面是空的
//e[]存放要插入到链表的元素,n是e[]的长度
LinkList* ToilInsert(LinkList *&L,ElementType e[],int n)
{
	//s是每次遍历到的待插入节点, r始终指向尾节点
	LinkList *s=0,*r=0;
	//初始化头节点
	//插入元素前保证头指针不为空
	L=InitList(L);

	//尾指针,初始化时指向头节点
	r=L;
	for(int i=0;i<n;i++)
	{
		//为新插入的节点分配空间
		s=(LinkList*)malloc(sizeof(LinkList));
		//数据成员——来自数组
		s->data=e[i];
		s->next=NULL;

		//节点间关联
		//第一次循环时, 是头指针的下一个节点是第一个插入的节点s
		//之后的循环是第i-1个插入的节点s的下一个节点指向第i个s
		r->next=s;
		//尾指针指向刚插入的节点
		r=s;
	}
	//插入完毕时,尾节点的指针成员指向NULL
	r->next=NULL;
	s=0;
	r=0;
	free(0);
	//free()的含义
	return L;
}

//遍历输出单链表元素
void DispList(LinkList *L)
{
	if(L!=NULL)
	{
		//p指向每一个实值节点
		//因为L是头指针,所以L->next是第一个含有实值的节点
		LinkList *p=L->next;
		while(p!=NULL)
		{
			printf("%d ",p->data);
			//p指向下一个节点
			p=p->next;
		}
	}
	else
		printf("链表为空\n");
	printf("\n");
}

/* 从单链表表中查找与给定元素值相同的元素在链表中的位置 */
int LinkListLocate(LinkList *L,ElementType x)
{
	int index=0;
	if(L!=NULL)
	{
		LinkList *p=NULL;
		
		p=L->next;
	
		//p为空(到头)或者p的数据成员满足条件
		// 先有p才有p->data ,否则报错
		//条件先大后小
		while(p!=NULL&&p->data!=x)
		{
			p=p->next;
			++index;
		}
		if(p==NULL)
		{
			printf("未找到符合条件的节点\n");
			index=-1;
		}
		else
		{
			p=NULL;
		}
		free(p);
	}
	else
		printf("链表为空\n");
	return index;
}
ElementType elementAt(LinkList *L,int index)
{
	ElementType e=-1;
	if(L!=NULL)
	{
		LinkList *p=NULL;
		p=L;
	
		if(index<0||index>=ListLength(L))
		{
			e=-1;
		}
		else
		{
			for(int i=0;i<=index;i++)
			{
				p=p->next;
			}
			e=p->data;
		}
		p=NULL;
		free(p);
	}
	else
		printf("链表为空\n");
	return e;
}

/* 从单链表中删除某给定元素 */
void LinkListDel(LinkList *&L,ElementType x)
{
	if(L!=NULL)
	{
		//_链表中删除一个节点必须找到该节点的前驱节点
		LinkList *pre=0,*p=0;
		pre=L;//pre初始是L,但始终是p的前驱
		p=L->next;//p指向开始节点

		while(p!=NULL && p->data!=x)
		{
			pre=p;
			p=p->next;
		}
		if(p==NULL)
		{
			printf("表中不存在元素%d\n",x);
			exit(0);
		}
		// 1->2  ...> 1-->3
		pre->next=p->next;

		pre=0,p=0;
		free(0);
	}
	else
		printf("链表为空\n");
}
//销毁单链表
void DestList(LinkList *&L)
{
	if(L!=NULL)
	{
		LinkList *pre=NULL,*p=NULL;

		//初始指向头指针
		pre=L;
		//实值第一个节点
		p=L->next;

		while(p!=NULL)
		{
			//第一次时销毁头节点
			free(pre);
			//pre向后移动一个节点
			pre=p;
			//p向后移动一个节点
			p=pre->next;
		}
		L=NULL;
		pre=NULL;
		p=NULL;
		free(NULL);
		printf("销毁成功!");
	}
//	free(pre);//
	else
		printf("链表为空\n");
}

LinkList* LinkListCreate( )//????
{
	LinkList *L=NULL;
	InitList(L);
	LinkList *p=NULL,*r=NULL;
	ElementType x;
	r=L;
	printf("please input data,input -1 is end\n");
	scanf("%d",&x);
	while (x!=-1)
	{
		p=(LinkList*)malloc(sizeof(LNode));
		p->data=x;
		r->next=p;
		r=p;
		scanf("%d",&x);
	}
	r->next=NULL;
	p=0;
	r=0;
	free(0);
	return L;
}
int insertNode(LinkList *&L,ElementType x,ElementType e)
{
	if(L!=NULL)
	{
		LinkList *p=0,*s=0;
		p=L->next;
		while(p!=NULL && p->data!=x )
		{
			p=p->next;
		}
		if(p==NULL)
			printf("节点%d不存在",x);
		else//p->data==x
		{
			s=(LinkList*)malloc(sizeof(LinkList));
			s->data=e;
			s->next=p->next;
			p->next=s;
		
		}
		p=0;
		s=0;
		free(0);
	}
	else
		printf("链表为空\n");
	return 0;
}
void interupt()
{
	printf("即将退出...\n.");
	exit(0);
}

int menu()
{
	int c;
	printf("1 初始化单链表\n");
	printf("2 清空单链表\n");
	printf("3 检查单链表是否为空\n");
	printf("4 遍历单链表\n");
	printf("5 求单链表的长度\n");
	printf("6 查找某位置的元素值\n");
	printf("7 查找与给定元素值相同的元素的首次出现位置\n");
	printf("8 向单链表中插入元素列表\n");
	printf("9 从单链表中删除元素\n");
	printf("10 结束程序\n");
	printf("11 销毁单链表\n");
	printf("12 删除值所在节点\n");
	printf("13 在指定元素后插入节点(输入)\n");
	scanf("%d",&c);
	printf("\n");
	return c;
}
int main()
{
	if(NULL==0)
		printf("y\n");
	ElementType e[]={3,7,8,6,2,5,5},x=0,data=0;
	int n=sizeof(e)/sizeof(ElementType);
	//L若不给初始NULL,则L不一定是NULL
	LinkList *L=NULL;
	int c=0;
	int index=0;
	while(1)
	{
		printf("\n");
		c=menu();
		switch(c)
		{
			case 1:
				L=InitList(L);//初始化
				break;
			case 2:
				ClearList(L);//清空
				break;
			case 3:
				printf("%d\n",isListEmpty(L));
				break;
			case 4:
				printf("单链表包含元素:");
				DispList(L);
				break;
			case 5:
				printf("单链表长度为:");
				printf("%d\n",ListLength(L));
				break;
			case 6:
				//在任何作用域内,假如存在变量初始化语句,该初始化语句不可以被跳过,一定要执行!
			//	 int index=0;//case中不能定义变量,但switch  case之间可以
				 printf("请输入要查找的下标");
				 scanf("%d",&index);				
				 printf("%d",elementAt(L,index));
				 printf("\n");
				break;
			case 7:
				printf("请输入要查找的元素");
				scanf("%d",&x);				printf("%d\n",LinkListLocate(L,x));
				break;
			case 8:
				ToilInsert(L,e,n);
				break;
			case 9:
				printf("请输入要删除的元素值");
				scanf("%d",&x);

				LinkListDel(L,x);
				break;
			case 10:
				interupt();
				break;
			case 11:
				DestList(L);
				break;
			case 12: 
				printf("请输入要删除的元素");
				scanf("%d",&x);
				LinkListDel(L,x);
				break;
			case 13:
				printf("请输入在哪个值后插入节点,以及要插入节点的值");
				scanf("%d %d",&x,&data);
				insertNode(L,x,data);

		}
	}
	L=0;
	free(0);
	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值