C語言實現單鏈表

#include<stdio.h>
#include<malloc.h>
#include<assert.h>

typedef int DataType;
typedef struct Node
{
	DataType data;//數據域
	struct Node* next;//保存下一個節點地址的指針域
}Node,*PNode;

void InitList(PNode* pHead)//初始化 傳二級指針
{
	assert(pHead);
	*pHead = NULL;
}

PNode BuyNode(DataType data)//申請新節點
{
	PNode pTemp = (PNode)malloc(sizeof(Node));//申請空間
	if(pTemp)//空間申請成功,若不成功直接返回NULL
	{
		pTemp->data = data;
		pTemp->next = NULL;
	}
	return pTemp;
}
void PushBack(PNode* pHead, DataType data)//尾插
{
	assert(pHead);
	if(*pHead == NULL)//空鏈表
	{
		*pHead = BuyNode(data);
	}
	else//鏈表不爲空
	{
		PNode pcur = *pHead;
		while(pcur->next)
		{
			pcur = pcur->next;
		}
		pcur->next = BuyNode(data);
	}
}
void PopBack(PNode* pHead)//尾刪
{
	assert(pHead);
	if(*pHead == NULL)//鏈表爲空
	{
		return;
	}
	else if((*pHead)->next == NULL)//鏈表只有一個節點
	{
		free(*pHead);
		*pHead = NULL;
	}
	else//鏈表有多個節點
	{
		PNode pcur = *pHead;
		PNode pre = pcur;
		while(pcur->next)
		{
			pre = pcur;
			pcur = pcur->next;
		}
		free(pcur);
		pre->next = NULL;
	}
}
void PrintList(PNode pHead)//正序打印 不需二級指針,不改變外部實參
{
	PNode pcur = pHead;
	while(pcur)
	{
		printf("%d->",pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
///////////////////////////////////面試題1//////單鏈表逆置打印 遞歸//////////////////////////////////////////
void PrintTail2Head(PNode pHead)
{
	if(pHead)
	{
		PrintTail2Head(pHead->next);
		printf("%d->",pHead->data);
	}
}
void PushFront(PNode* pHead, DataType data)//頭插
{
	assert(pHead);
	if(*pHead == NULL)//空鏈表與下面的非空情況可以合併到一起
	{
		*pHead = BuyNode(data);
	}
	else
	{
		PNode newnode = BuyNode(data);
		if(newnode)//必須判斷新節點是否創建成功,成功纔可以插入
		{
			newnode->next = *pHead;//先將節點鏈接起來,否則可能丟失原鏈表
		    *pHead = newnode;//然後讓第一個節點的指針再指向新節點
		}
	}
}
void PopFront(PNode* pHead)//頭刪
{
	assert(pHead);
	if(pHead == NULL)//分兩種情況 鏈表爲空
	{
		return;
	}
	//非空
	else
	{
	    PNode pTemp = *pHead;//先保存第一個節點
	    *pHead = (*pHead)->next;//再讓第一個節點向後移動
	    free(pTemp);//釋放掉第一個節點
	    pTemp = NULL;
	}
}
PNode Find(PNode pHead, DataType data)//查找data元素的位置
{
	PNode pTemp = pHead;
	while(pTemp)
	{
		if(pTemp->data == data)
		{
			return pTemp;
		}
		pTemp = pTemp->next;
	}
	return NULL;//不存在返回空
}
void Insert(PNode pos, DataType data)//在pos位置後插入元素
{
	PNode newnode = NULL;//爲啥要先賦空???
	if(pos == NULL)//插入位置是否合法
	{
		return;
	}
    newnode = BuyNode(data);//先申請新節點
	newnode->next = pos->next;//讓新節點的next指向pos的next
	pos->next = newnode;//然後讓pos的next指向新節點
}
void Erase(PNode* pHead, PNode pos)//要給出外部頭指針。因爲pos若爲頭結點 有可能改變頭結點的值
{
	assert(pHead);//鏈表是否存在
	if(pHead == NULL || pos == NULL)//鏈表爲空或位置不合法
	{
		return;
	}

	if(pos == *pHead)//刪除位置爲頭結點
	{
		*pHead = pos->next;//頭結點後移
		free(pos);//刪除頭節點
	}
	else
	{
		PNode pcur = *pHead;
		while(pcur->next != pos)
		{
			pcur = pcur->next;
		}
		pcur->next = pos->next;
		free(pos);
	}
}
/////////////////////////////////面試題2////////刪除非尾節點,不能遍歷鏈表 其實是刪除pos的下一個節點//////////////////
void DelNotTail(PNode pos)
{
	PNode Delnode =NULL;
	if(NULL == pos || pos->next ==NULL)
		return;
	Delnode = pos->next;
	pos->data = Delnode->data;
	pos->next = Delnode->next;
	free(Delnode);
}
/////////////////////////////////面試題3/////////////在非頭結點前插入元素(頭結點也可以) 在pos後插 然後交換值///////////////
void InsertNotHead(PNode pos, DataType data)
{
	PNode newnode = NULL;//?????????
	if(pos == NULL)
		return;
	newnode = BuyNode(pos->data);
	if(newnode)//必須判斷節點是否申請成功
	{
		newnode->next = pos->next;
	    pos->next = newnode;
		pos->data = data;
	}
} 
void Remove(PNode pHead, DataType data)//刪除值爲data的元素,直接調用Erase函數(傳引用)與Find函數(不傳引用)
{
	assert(pHead);
	Erase(&pHead, Find(pHead, data));
}
void RemoveAll(PNode* pHead, DataType data)//刪除所有值爲data的元素!!!!!!!!!!!!!!!!!!!!!有問題
{
	PNode pcur = NULL;
	PNode pre = NULL;
	assert(pHead);//鏈表是否存在

	pre = *pHead;//定義兩個指針 一個指向第一個節點
	pcur = pre->next;//指向第二個節點

	while(pcur)//遍歷一遍單鏈表
	{
		if(pcur->data == data)//若pcur指向的節點值爲data
		{
			pre->next = pcur->next;
			free(pcur);//釋放pcur
			//pcur = pre;//讓pcur指向前一個
			pcur = pre->next;
		}
		else
		{
			pcur = pcur->next;
		}
		
	
	}

	if((*pHead)->data == data)//如果頭節點值爲data的情況
	{
		pcur = *pHead;
		*pHead = (*pHead)->next;
		free(pcur);
	}
}

size_t Size(PNode pHead)//鏈表中元素個數
{
	PNode pcur = NULL;
	int count = 0;

	assert(pHead);
	pcur = pHead;
	while(pcur)
	{
		count++;
		pcur = pcur->next;
	}
	return count;
}
//PNode Front(PNode pHead)
//{
//	assert(pHead);
//	return pHead;
//}
PNode Back(PNode pHead)
{
	PNode pcur = pHead;
	if(NULL == pHead)
          return NULL;
	while(pcur->next)
	{
		pcur = pcur->next;
	}
	return pcur;
}
//int Empty(PNode pHead);
//////////////////////////////////////面試題//////////約瑟夫環/////////////////////////////////////////////
PNode JosephCircle(PNode pHead, size_t M)
{
	PNode pCur = pHead;
	PNode pTemp = NULL;
	if(pHead == NULL)
		return NULL;
	while(pCur->next != pCur)
	{
		size_t count = M;
		while(--count)
		{
			pCur = pCur->next;
		}
		pTemp = pCur->next;
		pCur->data = pTemp->data;
		pCur->next = pTemp->next;
		free(pTemp);
	}
	return pCur;
}
//////////////////////////////////////////////測試////////////////////////////////////////////
void FunTest4()
{
	PNode pHead, pos;
	int count = 0;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PushBack(&pHead, 5);

	//Erase(&pHead, Find(pHead, 3));
	//Remove(pHead, 2);
	//RemoveAll(&pHead, 2);///////////有問題啊
/////////////////////////////////////////////約瑟夫環//////////////////////////////////////
	pos = Back(pHead);//構環
	pos->next = pHead;//構環
	pHead = JosephCircle(pHead, 3);
	pHead->next = NULL;
	PrintList(pHead);

	
	//count = Size(pHead);
	//printf("%d\n",count);
}

void FunTest()
{
	PNode pHead;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PrintList(pHead);
	PushFront(&pHead, 5);
	PrintList(pHead);
	PrintTail2Head(pHead);

	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PrintList(pHead);

}

void FunTest1()
{
	PNode pHead;
	InitList(&pHead);
	PushFront(&pHead, 1);
	PushFront(&pHead, 2);
	PushFront(&pHead, 3);
	PushFront(&pHead, 4);
	PrintList(pHead);
	PopFront(&pHead);
	PrintList(pHead);
	PrintTail2Head(pHead);
}

void FunTest2()
{
	PNode pHead, pos;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	pos = Find(pHead, 2);
	Insert(pos,5);
	PrintList(pHead);
	Erase(&pHead, Find(pHead, 5));
	PrintList(pHead);

	Erase(&pHead, Find(pHead, 1));
	PrintList(pHead);

	DelNotTail(Find(pHead, 2));///只能刪除非尾節點
	PrintList(pHead);
}

void FunTest3()
{
	PNode pHead;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PrintList(pHead);
	InsertNotHead(Find(pHead, 2),5);
	PrintList(pHead);
}

int main()
{
	FunTest4();
	system("pause");
	return 0;
}


發佈了62 篇原創文章 · 獲贊 14 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章