【數據結構】課後作業——鏈表分離

P37.11

有一個整型鏈表,元素爲{a1,b1,a2,b2,......,an,bn}。將其分離爲A、B兩個鏈表,使得

A={a1,a2,......,an},B={bn,......,b2,b1}。

(1)算法的基本設計思想

遍歷原鏈表,取第一個元素尾插到A,第二個元素頭插到B。以此類推。

鏈表具有頭結點,因此需要從頭結點的後繼開始。

注意頭插時遇到的問題,頭插法是把B的頭指針指向當前節點,然後當前節點指向B頭指針原來指的節點。那麼便會出現如下情況:當前節點原來指向的指針消失了,我們無法找到那個節點。那麼就需要使用一個新的指針來指向那個節點,來保存它。要明確這一點:“改變一個節點的next指針,是改變該節點指向哪裏,原來指向的那個對象本身沒有變化”。知道這一點就不容易出錯了。

(2)代碼如下

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef int ElemType;
typedef struct LNode {
	ElemType data;
	struct LNode *next;
}LNode, *LinkList;
void printList(LinkList &L)
{
	printf("\n");
	LNode *s = L->next;
	while (s != NULL)
	{
		printf("%d ", s->data);
		s = s->next;
	}
}
LinkList CreatListend(LinkList &L)
{
	int x;
	L = (LinkList)malloc(sizeof(LNode));
	LNode *s, *r = L;
	scanf("%d", &x);
	while (x != 9999)
	{
		s = (LNode *)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;
		r = s;
		scanf("%d", &x);
	}
	r->next = NULL;
	return L;
}void Split(LinkList &L,LNode *A,LNode *B)
{
	LNode *Aend = A;//尾插法
	LNode *Bfirst = NULL;//頭插法
	LNode *Lnext;
	LNode *p = L->next;
	while (p!= NULL)
	{
		/*Aend->next = L->next;   原思路是懶得設指針p,直接用L->next代替,這樣在向後移動的時候,
		Aend = Aend->next;        就有L->next->next需要保存,我沒有保存它。
		B->next = L->next->next;  
		B->next->next = Bfirst;   這裏使得L斷裂了,中間出現了NULL,又沒有設指向之後元素的指針,之後的元素全部丟失。
		Bfirst = B->next;
		L = L->next->next;*/
		Aend->next = p;           //這裏設置了指針p,但實際上用L->next代替完全可以,只不過可讀性變差
		Aend = Aend->next;        //那麼對比上下的代碼
		Lnext = p->next->next;    //出錯原因在於沒有保存這個L->next->next->next,實際上在debug的時候我保存過,只不過保存的是L->next->next,保存錯了
		B->next = p->next;
		B->next->next = Bfirst;
		Bfirst = B->next;
		p = Lnext;
	}
	Aend->next = NULL;
}
void main()
{
	int count;
	LinkList L;
	LNode *A, *B;
	A = (LNode *)malloc(sizeof(LNode));
	B = (LNode *)malloc(sizeof(LNode));
	CreatListend(L);
	Split(L, A, B);
	printList(L);
	printList(A);
	printList(B);
}

(3)複雜度

時間複雜度O(n)

空間複雜度O(1)

PS:建議在對鏈表進行操作時,多使用結點指針,而不是直接L=L->next,太容易出錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章