c語言(隊列代碼分析)

隊列是在鏈表的基礎上,進行一種規範(增刪的順序)和屬性的增加(增加了項數)
這裏的例子是"顧客諮詢排隊問題"

一.數據的構建

1.項的構建---------只包含基礎數據類型,並用結構體打包

typedef struct item
{
	long arrive;//一位顧客加入隊列的時間
	int  processtime;//該顧客諮詢話費的時間
}Item;

2.節點的構建------項加上指向其他節點的指針

typedef struct node//創建鏈表-------------------------------節點
{
	Item item;
	struct node *next;
}Node;

3.隊列的構建(相對於鏈表的新增)-------2個指針(用來表明的前指針和用來標明隊列的尾指針)和項數

typedef struct queue//建立隊列---節點排列的一種方式----------隊列
{
	Node * front;
	Node * rear;
	int items;
}Queue;

二.隊列的一些申明

- 第一部分-----初始化以及一些檢查函數

/*初始化*/
void InitializeQueue(Queue * pq)
{
	//頭指針
	pq->front = NULL;
	//尾指針
	pq->rear = NULL;
	//項數
	pq->items = 0;
}

/*判斷----空*/
bool QueueIsEmpty(const Queue* pq)
{
	//如果項數是0  就返回true
	return pq->items == 0;
}

/*判斷---滿*/
bool QueueIsFull(const Queue* pq)
{
	//如果項數是滿的  就返回true
	return pq->items == MAXQUEUE;
}

/*查---項數*/
int QueueItemCount(const Queue* pq)
{
	//返回隊列中的項數
	return pq->items;
}

說明:
(1)初始化:隊列的初始化,讓2個指針指向null,項數爲0
(2)判斷是否爲空,是否爲滿:通過判斷項數的情況進行判斷
(3)查項數:返回項數的值即可

- 第二部分-----隊列的一些操作

/*增---添加項數*/
bool EnQueue(Item item, Queue*pq)
{
	/*添加項數只能從隊列後面的添加*/
	
	//創建一個節點
	Node * pnew;
	//---檢測是否創建成功---1.看隊列是否滿了 2.看分配空間是否成功
	if (QueueIsFull(pq))
		return false;

	pnew = (Node*)malloc(sizeof(Node));
	if (pnew == NULL)
	{
		fprintf(stderr, "爲節點分配空間出現問題\n");
		exit(EXIT_FAILURE);
	}

	//初始化節點----項,指針
	CopyToNode(item, pnew);
	pnew->next = NULL;
	//判斷節點是否爲第一個節點
	if (QueueIsEmpty(pq))
		pq->front = pnew;
	//---不是的話  節點的拼接操作----尾端的下一個指針 指向新節點
	else
	{
		pq->rear->next = pnew;
	}
	//更新尾部指針
	pq->rear = pnew;
	//項數加1
	pq->items++;

	return true;

}

/*刪---刪除項數*/
bool DeQueue(Item *pitem, Queue* pq)
{
	/*刪除項數只能從隊列前面刪*/

	//創建一個節點(替死鬼)指針
	Node * pt;
	//判斷隊列是否爲空--爲空的話 就執行不了刪除操作
	if (QueueIsEmpty(pq))
		return false;
	//調用函數  取出非指針部分(項)---這樣的刪除是可以恢復的(數據沒丟)??
	CopyToItem(pq->front, pitem);
	//新節點指針指向要被刪除的節點(首節點)
	pt = pq->front;
	//讓隊列首指針指向下一個節點
	pq->front = pq->front->next;
	//釋放替死鬼指針裏的內容
	free(pt);
	//隊列項目數減1
	pq->items--;
	//判斷隊列裏的項目數是否爲0---如果爲0  就不存在尾指針
	if (pq->items == 0)
	{
		pq->rear = NULL;
	}
	return true;
}

/*清空*/
void EmptyTheQueue(Queue* pq)
{
	/*相當於清空了所有的節點*/
	//創建一個項 作爲垃圾站(存放要被刪除的項)
	Item dummy;
	//如果隊列不是空的--就一直刪除節點
	while (!QueueIsEmpty(pq))
	{
		DeQueue(&dummy, pq);
	}
}

說明:

- (1)增添項數的操作:通過創建節點,把節點加入到隊列中實現

其中節點的初始化用到了輔助函數

static void CopyToNode(Item item, Node* pn)
{
	pn->item = item;
}


輔助函數是把項中的內容(item)送到節點中項的部分(pn->item = item;)
這個函數的操作流程是:
1.創建一個指向節點結構的指針(pnode)------作用類似於"current"指針
2.對隊列情況的判斷-------滿了就不能添加了
3.對此指針指向節點的初始化(先請求分配空間,分配空間同意後,項(輔助函數)和指針(指向下一節點)的初始化)
4.對隊列情況的判斷------如果(1)隊列是空的,這個新節點就是"頭部了"(用前指針指向這個節點)
(2)隊列不是空的:那就讓隊列"屁股節點"(pq->rear)的"小尾巴"(pq->rear->next)指向這個節點(pnode)
5.更新"屁股節點"-------讓"屁股節點"指針指向新節點(pq->rear = pnew;)
6.更新項數;

- (2)刪除項數的操作:通過創建節點指針,讓這個指針指向要刪除的節點,刪除這個指針所指向的內容即可
其中將節點中項部分的內容取出(我感覺這裏這麼做只是爲了做個刪除備份)用到了輔助函數:

static void CopyToItem(Node*pn, Item*item)
{
	*item = pn->item;
}

輔助函數是把要刪除的節點(pn)中的項(pn->item)做個備份(讓item指向這個數據)(注意這裏不是地址傳遞而是值傳遞)
這個函數的操作流程是:
1.創建一個指向節點結構的指針(pt)------作用類似於"current"指針
2.對隊列的情況的判斷-----空的就無法執行操作
3.對前指針進行備份,轉移處理:
(1)備份:(把第一個節點的項的內容複製一下)
(2)轉移:讓pt和前指針指向同一個節點(形成current"節點")------pt = pq->front;
再讓前指針指向前指針的"下一個"從而形成轉移--------pq->front = pq->front->next;
4.釋放pt指針所指向的節點
5.項數的改變
6.如果項數爲0了,隊列的尾部(pq->rear"後指針")要指向空(注意"後指針"和"後指針的尾巴",前者是有實際節點的,後者一般爲null).

- (3)清空處理:就是對每個節點進行刪除操作

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