写给自己看的单链表(2):进阶操作

!!!Attention:以下操作中的单链表均带有头结点!!!
1.反转
方法有好几种,可以参考看图理解单链表的反转,这里采用3个指针prev、current和s遍历单链表,逐个节点进行反转的方法。当节点数为0或1时没有必要进行反转,所以首先要进行判断。最后要注意把head指针指向正确的节点。

void ReverseList(Lnode *head)
{
	if (head == NULL || head->next == NULL || head->next->next == NULL)
		return;
	Lnode *prev, *current, *s;
	current = head->next;
	prev = NULL;
	while (current != NULL) {
		s = current->next;
		current->next = prev;
		prev = current;
		current = s;
	}
	head->next = prev;
}

2.合并
有就地合并和新建一个链表两种方法。这里采用就地合并,合并后原先的链表就不能再被使用了。代码实现可以用递归或非递归,这里暂时给出递归实现,非递归实现日后再补上。可以参考有序单链表的合并这篇文章。
注意要对头结点做特殊的处理,因此将程序分为了MergeList和MergeListCore两个函数来实现,若是链表不带头结点,则直接调用MergeListCore即可。MergeList中选取了合适的头结点后,要将用不到的另一个链表的头结点free,否则会造成内存泄漏。MergeListCore中开头要给出当节点为NULL时直接返回,不然递归就不会停止了。此外还要考虑到两个链表中数据元素相等的情况,在判断中采用了head1->next->data <= head2->next->data,小于等于而非只是小于。

Lnode *MergeList(Lnode *head1, Lnode *head2) //Recursive, in place
{
	if (head1->next == NULL) {
		free(head1);
		return head2;
	}
	if (head2->next == NULL) {
		free(head2);
		return head1;
	}

	if (head1->next->data <= head2->next->data) {
		head1->next = MergeListCore(head1->next, head2->next);
		free(head2);
		return head1;
	}
	if (head1->next->data > head2->next->data) {
		head2->next = MergeListCore(head1->next, head2->next);
		free(head1);
		return head2;
	}
}

Lnode *MergeListCore(Lnode *head1, Lnode *head2) 
{
	if (head1 == NULL) 
		return head2;
	if (head2 == NULL)
		return head1;
	
	if (head1->data <= head2->data) {
		head1->next = MergeListCore(head1->next, head2);
		return head1;
	}
	if (head1->data > head2->data) {
		head2->next = MergeListCore(head1, head2->next);
		return head2;
	}
}

猜你喜欢

转载自blog.csdn.net/u013213111/article/details/88666880