C語言常見單鏈表面試題(2)

問題定義:ide

      寫一個函數Merge函數,該函數有兩個參數,都是遞增的鏈表,函數的功能就是合併這兩個遞增的鏈表爲一個遞增的鏈表,Merge的返回值是新的鏈表。新鏈表由前兩個鏈表按元素遞增順序合併而成,也就是說它不會建立新的元素。函數

好比:這裏有兩個鏈表,分別是spa

list1: 5->10->15指針

list2: 2->3->20orm

Merge函數返回一個指向新鏈表的指針,新鏈表應該是以下這樣的:2->3->5->10->15->20遞歸

     程序須要考慮以下狀況:兩個鏈表(函數參數)都有可能爲空,可能連個鏈表其中一個爲空,可能兩個鏈表相等,也可能其中一個鏈表已經遍歷完了,另外一個鏈表還有不少元素,因此須要首先處理特殊狀況。it

一、非遞歸實現class

pLinkNode Merge(pList l1, pList l2)
{
	pList pNewHead = NULL;
	pLinkNode cur = NULL;
	assert(l1);
	assert(l2);
	if (l1 == l2)//鏈表相等
	{
		return l1;
	}
	if ((l1 == NULL) && (l2 != NULL))//L1爲空
	{
		return l2;
	}
	if ((l1 != NULL) && (l2 == NULL))//l2爲空
	{
		return l1;
	}
	if (l1->data < l2->data)
	{
		pNewHead = l1;
		l1 = l1->next;
		pNewHead->next = NULL;
	}
	else
	{
		pNewHead = l2;
		l2 = l2->next;
		pNewHead->next = NULL;
		
	}
	cur = pNewHead;//肯定頭指針
	
	while ((l1) && (l2))
	{
		if (l1->data < l2->data)
		{
			cur->next = l1;
			l1 = l1->next;
		}
		else
		{
			cur->next = l2;
			l2 = l2->next;
		}
		cur = cur->next;
	}
	if(l1==NULL)
	{
		cur->next = l2;
	}
	else
	{
		cur->next= l1;
	}
	return pNewHead;
}

二、合併操做是很是適合用遞歸來完成的一類操做,遞歸實現將會比迭代實現更加清晰且易於理解。儘管如此,你可能也不肯意使用遞歸來實現這個操做,由於遞歸方法所使用的棧空間與鏈表的長度成正比。List

思路:能夠將兩個有序單鏈表的合併簡化爲在兩條單鏈表中一直尋找較小的頭節點。可是首先仍是要考慮特殊狀況遍歷

pLinkNode _Merge(pList l1, pList l2)
{
	pList pNewHead = NULL;
	pLinkNode cur = NULL;
	assert(l1);
	assert(l2);
	if (l1 == l2)//鏈表相等
	{
		return l1;
	}
	if ((l1 == NULL) && (l2 != NULL))//L1爲空
	{
		return l2;
	}
	if ((l1 != NULL) && (l2 == NULL))//l2爲空
	{
		return l1;
	}
	if (l1->data < l2->data)
	{
		pNewHead = l1;
		pNewHead->next = _Merge(l1->next, l2);
	}
	else
	{
		pNewHead = l2;
		pNewHead->next = _Merge(l1, l2->next);

	}
	return pNewHead;
}
相關文章
相關標籤/搜索