List_有頭結點_完整

惠hiuj發表於2024-05-07
/**************************************************************************************************************
*
*	file name:	Zqh_連結串列.c
* 	author	 :	keyword2024@163.com
* 	date	 :	2024/05/05
*	function :	連結串列的增刪改查排序
*	note	 :	模板
*	
*  Copyright (c)  2023-2025   keyword2024@163.com    All right Reserved
**************************************************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

typedef struct Node
{
	int data;
	struct Node *pNext;
}NODE,*PNODE;

PNODE create_list();       
void traverse_list(PNODE);
bool is_empty(PNODE);     
int length_list(PNODE); 
void sort_list(PNODE);    
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int *);
void clear_list(PNODE);
/**************************************************************************************************************
以下為操作連結串列的演算法,該連結串列為單連結串列。
連結串列以頭指標為索引,頭指標指向頭節點,頭節點指向首節點,以此類推,直到尾節點。
頭節點中不存放資料,只存放指向首節點的指標,
設定頭節點的目的是為了方便對連結串列的操作,如果不設定頭節點,而是直接由頭指標指向首節點,
這樣在對頭指標後的節點進行插入刪除操作時就會與其他節點進行該操作時有所不同,便要作為一種特殊情況來分析
**************************************************************************************************************/

int main(void)
{
	int len;
	int data_del;
	PNODE pHead = NULL;

	//建立連結串列並遍歷輸出
 	pHead = create_list();
	traverse_list(pHead);

	//求連結串列長度,並輸出
	len = length_list(pHead);
	if(!is_empty(pHead))
		printf("the length of the list is:%d\n",len);
	
	//向連結串列中插入資料,並重新遍歷輸出
	if(insert_list(pHead,3,78))
		printf("insert succeed,");
	else
		printf("insert failed,");
	traverse_list(pHead);

	//從連結串列中刪除資料,並重新遍歷輸出
	if(delete_list(pHead,3,&data_del))
		{
		  printf("delete succeed,the deleted data is:%d\n",data_del);
		}
	else
		printf("delete failed,");
	traverse_list(pHead);
	
	//對連結串列排序,重新遍歷輸出
	sort_list(pHead);
	printf("After sorted,");
	traverse_list(pHead);	
	
	//清空連結串列,遍歷輸出(無資料輸出)
	clear_list(pHead);
	printf("After cleared,");
	traverse_list(pHead);	
	return 0;
}

/*
  建立一個連結串列,並返回頭指標
*/
PNODE create_list()
{
	int val;
	PNODE pHead =(PNODE)malloc(sizeof(NODE));
	PNODE pCurrent = pHead;
	pCurrent->pNext = NULL;
	if(NULL == pHead)
	{
		printf("pHead malloc failed!");
		exit(-1);
	}
	printf("Input first data(q to quit):");
	while(scanf("%d",&val)==1)
	{
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if(NULL == pNew)
		{
			printf("pNew malloc failed!");
			exit(-1);
		}
		pNew->data = val;
		pCurrent->pNext = pNew;
		pNew->pNext = NULL;
		pCurrent = pNew;
		printf("Input next data(q to quit):");
	}

	return pHead;	
}

/*
遍歷連結串列
*/
void traverse_list(PNODE pHead)
{
	PNODE pCurrent = pHead->pNext;
	printf("now dataes in the list are:\n");
	while(pCurrent != NULL)
	{	
		printf("%d ",pCurrent->data);
		pCurrent = pCurrent->pNext;
	}
	printf("\n");
	return ;
}

/*
判斷連結串列是否為空
*/
bool is_empty(PNODE pNode)
{
	if(NULL == pNode->pNext)
		return true;
	else 
		return false;
}

/*
求連結串列長度,即節點總數(不計入頭節點)
*/
int length_list(PNODE pNode)
{
	int count = 0;
	PNODE pCurrent = pNode->pNext;
	while(pCurrent != NULL)
	{
		count++;
		pCurrent = pCurrent->pNext;		
	}

	return count;
}

/*
冒泡法對連結串列排序
*/
void sort_list(PNODE pHead)
{
	PNODE p,q;
	int temp;
	for(p=pHead->pNext;p!=NULL;p=p->pNext)
	    for(q=p->pNext;q!=NULL;q=q->pNext)
		{
		   if(p->data>q->data)
	              {
			 temp = p->data;
			 p->data = q->data;
			 q->data = temp;
		      }
		}

	return ;
}

/*
在第pos個節點的後面插入一個新的節點,該節點中的資料為val
*/
bool insert_list(PNODE pHead,int pos,int val)
{
	int i = 0;
	PNODE p = pHead;

        //i為0時,p指向第0個節點(這裡指沒有實際資料的頭節點,不計入連結串列節點總數),
	//i為1時,p指向第1個節點,i為幾,p就指向第幾個節點
	while(p!=NULL && i<pos)
	{
	   p = p->pNext;
	   i++;
	}

	//當pos的值大於連結串列長度時,便會出現這種情況
	if(i>pos || p==NULL)
	   return false;

	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if(NULL == pNew)
	{
	   printf("pNew malloc failed!");
	   exit(-1);
	}
	pNew->data = val;
	pNew->pNext = p->pNext;
	p->pNext = pNew;

	return true;
}

/*
刪除第pos個節點,並將刪除的資料儲存在pData指標所指向的位置
*/
bool delete_list(PNODE pHead,int pos,int *pData)
{
	int i = 0;
	PNODE p = pHead;

	//p最終指向第pos個節點前面的節點
	//如果下面兩句分別改為while(p!=NULL && i<pos)和if(i>pos || p==NULL),則p最終指向第pos個節點,
	//這樣因為得不到第pos個節點前面的那個節點,因此無法將pos前後兩個節點連結起來
	while(p->pNext!=NULL && i<pos-1)
	{
	   p = p->pNext;
	   i++;
	}

	//當pos的值大於連結串列長度時,便會出現這種情況
	if(i>pos-1 || p->pNext==NULL)
	   return false;

	PNODE q = p->pNext;
	*pData = q->data;
	p->pNext = p->pNext->pNext;
	free(q);
	q = NULL;
	return true;
}

/*
清空連結串列,即使連結串列只剩下頭節點(頭節點中沒有資料)
*/
void clear_list(PNODE pHead)
{
	PNODE p = pHead->pNext;
	PNODE r = NULL;
	while(p != NULL)
	{
	   r = p->pNext;
	   free(p);
	   p = r;
	}
	pHead->pNext = NULL;
	return ;
}

相關文章