单向链表的操作

C语言实现单向链表的新建节点、插入节点、删除节点、循环遍历输出节点、返回链表的节点个数、清空链表、返回指定位置的节点,倒置链表。。。。等等

具体见代码:

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


struct MyList//单向链表
{
	int data;
	struct  MyList *next;
};

//动态新建一个节点
struct MyList * CreateNode()
{
	return calloc(sizeof(struct MyList), 1);
}

//循环遍历一个链表
void Traverse(struct MyList * ls)
{
	struct MyList *p = ls;
	while (p)
	{
		printf("%d\n", p->data);
		p = p->next;
	}
}

//在指定位置(相对于ls指向的位置偏移pos个位置)插入元素,并返回指向这个被插入的元素
struct MyList * Insert(struct MyList *ls,int pos, int d)
{
	struct MyList *p = ls;
	while (p&&pos--)
	{
		p = p->next;
	}

	if (p==NULL)
	{
		return NULL;//pos指定的位置大于链表的节点数
	}

	//新建一个节点
	struct MyList *node = calloc(sizeof(struct MyList), 1);
	node->data = d;

	node->next = p->next;
	p->next = node;

	//return node;
}

	//删除相对于ls指定位置的节点
int Delete(struct MyList *ls, int pos)
{
	struct MyList *p = ls;
	while (p&&--pos)
	{
		p = p->next;
	}
	if (p == NULL)
	{
		return -1;//删除的位置超过了最后一个节点,pos的位置不合理,删除失败
	}

	//printf("   %d   ", p->data);
	
	//两种删除方法之一:
	//struct MyList *tmp = p->next->next;
	//free(p->next);
	//p->next= tmp;

	//两种删除方法之二:
	struct MyList *tmp = p->next;
	p->next = tmp->next;
	free(tmp);
	


	return 0;//删除成功
}

//返回链表的元素个数
int Count(struct MyList *ls)
{
	int count=0;
	struct MyList *p = ls;
	while (p != NULL) //等价于 while(p)
	{
		count++;
		p = p->next;
	}
	return count;
}

	//清空链表,只保留首节点
	void Clear(struct MyList *ls)
	{
		struct MyList *p = ls->next;
		struct MyList *p1 = ls;
		while (p)//第二个节点
		{
			struct  MyList *temp = p->next;
			free(p);
			p = temp;
		}

		p1->next = NULL;
	}

	int Empty(struct MyList *ls)
	{
		struct MyList *p = ls;
		if (p->next != NULL)
			return 1;//非空
		else
			return 0;//空
	}

	//返回指定位置的节点
	struct MyList * Locate(struct MyList *ls,int pos)
	{
		struct MyList *p = ls;
		while (p&&--pos)
		{
			p = p->next;
		}

		if (p == NULL)
			return NULL;

		return p;
	}


	//返回指定元素值的节点
	struct MyList * GetNodeByData(struct MyList *ls, int value)
	{
		struct MyList *p = ls;
		while (p)
		{
			if (value == p->data)
				return p;
			else
				p = p->next;
		}
		return NULL;
	}

	//返回指定元素值节点的位置
	int GetPosByData(struct MyList *ls, int value)
	{
		int index = 0;
		struct MyList *p = ls;
		while (p)
		{
			if (value == p->data)
				return index;
			
			p = p->next;
			index++;
		}
		return -1;
	}

	//得到链表的最后一个节点
	struct MyList * GetLastNode(struct MyList *ls)
	{
		struct MyList *p = ls;
		while (p->next)
		{
			p = p->next;
		}
		return p;
	}

	//合并两个链表,不合并第二个链表的头
	struct MyList * MergeList(struct MyList * list1, struct MyList *list2)
	{
		struct MyList *p = list1;
		while (p->next)
		{
			p = p->next;
		}
		p->next = list2->next;

		free(list2);//list2的链表头不要了
	}

	//链表的倒置
	void Reverse(struct MyList *ls)
	{
		if (ls->next == NULL)//只有头结点
			return ls;
		if (ls->next->next == NULL)//只有头结点和第一个节点
			return ls;

		struct MyList * newlast = ls->next;//倒置后的最后一个节点(倒置前的第二个节点)

		struct MyList *PPre = ls;
		struct MyList *CCur = ls->next;
		struct MyList *NNext = NULL;

		while (CCur)
		{
			NNext = CCur->next;
			CCur->next = PPre;

			PPre = CCur;
			CCur = NNext;
		}

		ls->next = PPre;
		newlast->next = NULL;
	}





int main()
{
	struct  MyList *l1 = CreateNode(); // calloc(sizeof(struct MyList), 1);
	struct  MyList *l2 = CreateNode(); // calloc(sizeof(struct MyList), 1);
	struct  MyList *l3 = CreateNode(); // calloc(sizeof(struct MyList), 1);
	struct  MyList *l4 = CreateNode(); // calloc(sizeof(struct MyList), 1);
	struct  MyList *l5 = CreateNode(); // calloc(sizeof(struct MyList), 1);
	
	l1->next = l2;
	l2->next = l3;
	l3->next = l4;
	l4->next = l5;
	l5->next = NULL;

	l1->data = 100;
	l2->data = 200;
	l3->data = 300;
	l4->data = 400;
	l5->data = 500;
	
	Traverse(l1);

	printf("----------------------------------\n");
	Insert(l1, 2, 25);//相对于l1,偏移2个的位置插入,即在300之后插入25;
	//如果Insert函数里面是--pos,则在300之前插入25;
	Insert(l1, 2, 26);
	Insert(l1, 2, 27);
	Insert(l1, 2, 28);
	//注意输入的顺序,遍历输出是:100,200,300,28,27,26,25,400,500

	Traverse(l1);
	printf("----------------------------------\n");

	Delete(l1, 2);//删除300,注意是--pos
	Traverse(l1);

	printf("链表中元素的个数是:%d\n", Count(l2));//输出7,从l2开始的
	printf("----------------------------------\n");

	//Clear(l1);
	Traverse(l1);
	printf("----------------------------------\n");

	struct MyList *pt=Locate(l1, 3);
	printf("第%d个元素的值是%d\n",3,pt->data);
	
	int ii = GetPosByData(l1, 28);
	printf("值为28的节点的位置是:%d\n", ii);//从0开始
	
	struct MyList *ppp = GetLastNode(l1);
	printf("最后一个节点的值是:%d\n", ppp->data);
	
	printf("----------------------------------\n");

	//新建另一个链表
	struct MyList * node21 = CreateNode();
	struct MyList * node22 = CreateNode();
	struct MyList * node23 = CreateNode();
	struct MyList * node24 = CreateNode();
	struct MyList * node25 = CreateNode();

	node21->next = node22;
	node22->next = node23;
	node23->next = node24;
	node24->next = node25;
	node25->next = NULL;

	node21->data = 2001;
	node22->data = 2002;
	node23->data = 2003;
	node24->data = 2004;
	node25->data = 2005;

	//MergeList(l1, node21);
	Traverse(l1);
	printf("----------------------------------\n");

	Reverse(l1);
	Traverse(l1);
	
	return 0;
}

效果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值