PTA-链表学习-----奇数值结点链表

奇数值结点链表

解法一

struct ListNode *readlist()
{
	
	struct ListNode *head = NULL, *p;
	int data=0;
	
	while(scanf("%d", &data)&&data != -1)
	{
		struct ListNode *q = (struct ListNode *)malloc(sizeof(struct ListNode));//为节点分配存储空间
		if(q!=NULL)
		{
			q->data = data;
			q->next = NULL;
		}//增加了一个节点
		else exit(1);//异常退出
		if(head != NULL)
		{
			p->next = q;
		}
		else head = q;
		p = q;
	}
	return head;
}
struct ListNode *getodd( struct ListNode **L )
{
	struct ListNode *head0 = NULL, *head1 = NULL, *p0, *p1;
	while((*L) != NULL)
	{
		int data = (*L)->data;
		struct ListNode *q = (struct ListNode *)malloc(sizeof(struct ListNode));
		if(data%2)
		{
			if(q != NULL)
			{
				q->data = data;
				q->next = NULL;
			}
			else exit(1);
			if(head1 != NULL)
			{
				p1->next = q;
			}
			else head1 = q;
			p1 = q;
		}
		else
		{
			if(q != NULL)
			{
				q->data = data;
				q->next = NULL;
			}
			else exit(1);
			if(head0 != NULL)
			{
				p0->next = q;
			}
			else head0 = q;
			p0 = q;
		}
		(*L) = (*L)->next;
	}
	*L = head0;//L存储偶数值
	return head1;//返回奇数值 
}

此解法是刚学习链表时从网上找到的一种解法,具体思路为新建两个链表,然后将L链表中的值各自放到对应链表中,最后把偶数链表的头节点给(*L)。
此解法需要申请新的内存,若不能及时释放会造成内存空间的浪费, 所以不能算是最优的算法。

解法二

struct ListNode *readlist() {
	//尾插
	struct ListNode *head = NULL, *tail = NULL;
	int a;

	scanf("%d", &a);
	while(a!=-1) {
		struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
		newNode->data = a;
		newNode->next = NULL;
		if(head == NULL) {
			tail = head = newNode;
		} else {
			tail->next = newNode;
			tail = newNode;
		}
		scanf("%d", &a);
	}
	tail->next = NULL;
	return head;
}
struct ListNode *getodd(struct ListNode **L) {
	/*解题思路, 将L链表中的奇数节点从链表中提出来放入新得奇数链表, L存放偶数节点*/ 
	
	/*p1为计数指针,从L链表的头节点数到尾节点, p2为奇数链表计数(定位)指针, prev用于记录偶数链表当前节点*/
	struct ListNode *p1 = (*L), *head1 = NULL, *p2 = NULL, *prev = NULL;//head1奇数链表的头
	
	while(p1) {

		if(p1->data%2!=0) {
			if(head1 == NULL) {//只运行一次,放入奇数链表的头节点 
				head1 = p1;
				p2 = head1;//定位奇数链表 

			} else {
				p2->next = p1;//经典---尾添加节点 
				p2 = p1;
			}
			if(prev == NULL) {
				(*L) = (*L)->next;//也只运行一次,如果L链表头节点为奇数时,L链表的头指向下一个, 如果L链表头节点为偶数节点时,此判断不会运行 
			} else {
				if(p1->next == NULL) {//经典--打断指针指向 
					prev->next = NULL;
				} else {
					prev->next = p1->next;
				}
			}
		} else {		//**********此处由于未将prev作用弄清楚废了好长时间*********// 
			prev = p1;//(地址:(*L) = p1 = prev.) prev应该定位的是偶数链表的当前节点,不应该直接放在外层 
		}

		p1 = p1->next;
	}
	if(head1!=NULL) {
		p2->next = NULL;//将奇数链表的尾节点的指针置空,没啥好说的 
	}

	return head1;
}

此解法为学习链表一周多后自己的解法,具体解法思路在代码中,此解法是在没有借鉴其他解法的情况下自己想出来的,虽然花费了好长时间思考,但着实能够加强思考问题的逻辑性与考虑的全面性,也同时使我加深和巩固了链表的相关知识,美滋滋。

tips:

1.链表中的指针主要是地址之间的指来指去,对链表操作时应注意地址指向,像空节点(NULL)在指向下一个节点时会发生越界(段错误)。
2.操作链表要注意链表的头不能丢,丢了头就找不到链表啦。
3.注意整个过程的逻辑性与思考问题的全面性,问题复杂时建议先在纸上画个简单的例子,帮助思考过程中的判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值