1. 程式人生 > >動態鏈式佇列詳解及完整例項演示

動態鏈式佇列詳解及完整例項演示

佇列

       佇列(Queue)是隻允許在一端(隊尾rear)進行插入,而在另一端(隊頭front)進行刪除的運算受限的線性表。它是一種可以實現“先進先出”(FIFO)的儲存結構。佇列在具體應用中通常用連結串列或者陣列來實現,因此我們也常常將佇列分為靜態佇列(陣列佇列),鏈式佇列(主要以連結串列方式進行操作)。當佇列中沒有元素時,我們稱之為空佇列。一般佇列的儲存結構是順序儲存,當佇列的儲存結構是鏈式儲存結構(即佇列中每個元素都包含一個指向其後繼的指標,最後一個指標元素也就是尾結點的指標域為NULL)時,就是鏈式隊列了。和棧不同,佇列通常需要對其兩端進行操作,而棧一般只需對通過棧頂指標進行操作即可。

對鏈式佇列的相關操作思路

       

typedef struct Node
{
	int data;//資料域
	struct Node *pNext;//指標域
}NODE,*PNODE;
typedef struct Queue
{
	PNODE pFront;//始終指向頭結點(沒有實際含義的結點)
	PNODE pRear;//始終指向尾結點(注意:尾結點資料域含有效資料,但指標域為空)
}QUEUE,*PQUEUE;//PQUEUE等價於struct Queue*

偽演算法:

             1.初始化。初始化的目的主要是為了造空佇列

              void init(PQUEUE pQ)//造空佇列

               {

                     造頭結點;

                     讓尾結點指向頭結點;

                     將尾結點指標域賦為NULL; 

                     return;

               } 

            2.入隊

             void enter(PQUEUE pQ,int val)

             {

                       造新節點;

                       將val賦給新節點的資料域;

                       將新節點的指標域賦為NULL;

 ·                     將尾結點的指標域指向新節點;

                       使該新結點成為尾結點;

              }

            3.出隊

              bool del(PQUEUE pQ)

               {

                         找到第一個有效節點;

                         判斷佇列是否為空;

                         不為空時輸出有效節點的資料域;      

                         找出第一個有效節點,並讓指向第一個結點的指標指向第二個;

                         釋放第一個結點所佔記憶體;

                         注意:若佇列中只有一個元素時,將頭結點的地址賦給隊尾,讓尾結點成為無效結點;

               }

              4.遍歷:在輸出尾結點的值後,跳出迴圈。當然前提先要判斷該佇列是否為空;

             5. 清空:先判斷該佇列是否為空;再 找出第一個有效結點,用一個臨時變數儲存下一個有效節點的地址,並讓隊頭(隊首)指向該地址,然後釋放第一個結點所佔記憶體,最後將下一個結點的地址賦給該佇列的頭結點(即讓頭結點指向下一個結點的地址),如此進行迴圈直到隊尾刪除完(只剩頭結點,再讓尾結點指向頭結點,這樣相當於又完成了一次對該鏈式佇列的初始化)。 

例項說明:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
	int data;//資料域
	struct Node *pNext;//指標域
}NODE,*PNODE;
typedef struct Queue
{
	PNODE pFront;//始終指向頭結點(沒有實際含義的結點)
	PNODE pRear;//始終指向尾結點(注意:尾結點資料域含有效資料,但指標域為空)
}QUEUE,*PQUEUE;//PQUEUE等價於struct Queue*
void init(PQUEUE);//初始化佇列
void enter(PQUEUE,int);//入隊
bool del(PQUEUE);//出隊
bool traverse(PQUEUE);//遍歷
int length(PQUEUE);//求鏈式佇列長度
bool clear(PQUEUE);//清空鏈式佇列

int main()
{
	QUEUE Q;
	init(&Q);
	enter(&Q,1);
	enter(&Q,2);
	enter(&Q,3);
	traverse(&Q);
	del(&Q);
    traverse(&Q); 
    printf("佇列長度為:%d\n",length(&Q));
	clear(&Q);
	printf("清空後");
    traverse(&Q);  
	return 0;
}
void init(PQUEUE pQ)//造空佇列
{
	pQ->pFront=(PNODE)malloc(sizeof(NODE));//造頭結點,並讓pFront指向該頭結點
	if(NULL==pQ->pFront)
	{
		printf("動態記憶體分配失敗!\n");
		exit(-1);//終止程式執行
	}
	pQ->pRear=pQ->pFront;
    pQ->pFront->pNext=NULL;
	return; 
}
void enter(PQUEUE pQ,int val)
{
	PNODE pNew=(PNODE)malloc(sizeof(NODE));//造新臨時結點
	if(NULL==pNew)
	{
		printf("動態記憶體分配失敗!\n");
		exit(-1);//終止程式執行
	}
	pNew->data=val;
	pNew->pNext=NULL;
	pQ->pRear->pNext=pNew;
	pQ->pRear=pNew;
	return;
}
bool del(PQUEUE pQ)//出隊
{
	PNODE p=pQ->pFront->pNext;//讓p指向隊頭的第一個有效節點	
	if(NULL==p)
	{
		printf("佇列為空,出隊失敗!\n");
		return false;
	}
	else
	{
		printf("出隊元素的值為:%d\n",p->data);
		if(p==pQ->pRear)//如果是隊尾,說明只有一個有效結點
			pQ->pRear=pQ->pFront;//因為pFront始終指向的是頭結點的地址,這裡將頭結點的地址賦給隊尾(此時隊尾成為無效結點)
		pQ->pFront->pNext=p->pNext;
		free(p);
		p=NULL;
		return true;
	}
}
bool traverse(PQUEUE pQ)
{
	PNODE p=pQ->pFront;
	if(NULL==p->pNext)
	{
		printf("佇列為空,遍歷失敗!\n");
		return false;
	}
	printf("佇列元素有:");
	while(p!=pQ->pRear)
	{
		p=p->pNext;
		printf("%d  ",p->data);
	}
	printf("\n");
    return true; 
}
int length(PQUEUE pQ)
{
	int len=0;
	PNODE p=pQ->pFront;
	if(NULL==p->pNext)
	{
		printf("佇列為空!\n");
		return 0;
	}
	while(p!=pQ->pRear)
	{
		p=p->pNext;
		++len;
	}
	return len;
}
bool clear(PQUEUE pQ)
{
	PNODE p=pQ->pFront->pNext,q;//讓p指向隊頭的第一個有效節點	
	if(NULL==p)
	{
		printf("佇列為空,清空失敗!\n");
		return false;
	}
	else
	{
		while(p!=pQ->pRear)
		{
			q=p->pNext;//用q來儲存p的下一個結點的地址
			pQ->pFront=q;
			free(p);
			p=q;
		}
		pQ->pRear=pQ->pFront;
        return true; 
	}	
}

注意

       1.   在上篇棧中,壓棧(進棧)的時候pTop指向了第一個有效結點,而該鏈式佇列中入隊的時候pFront仍然還是指向了佇列初始化是的頭結點(沒有實際含義的結點)。

       2.  該鏈式佇列中,pRear始終指向尾結點,隊尾資料域為有效資料,但其指標域為空;pFront始終指向頭結點(附結頭結點的目的和上篇棧中的一樣,為了方便對鏈式進行操作)。如:PNODE p=pQ->pFront->pNext;就可以讓p指向隊首(第一個)有效結點

相關推薦

動態佇列完整例項演示

佇列        佇列(Queue)是隻允許在一端(隊尾rear)進行插入,而在另一端(隊頭front)進行刪除的運算受限的線性表。它是一種可以實現“先進先出”(FIFO)的儲存結構。佇列在具體應用中通常用連結串列或者陣列來實現,因此我們也常常將佇列分為靜態佇列(陣列佇列

剖分模板

這幾天學習了一下樹鏈剖分,順便寫一下我的理解、 早上看了一下別人的講解,雲裡霧裡,終於算是搞懂了、 樹鏈剖分是解決在樹上進行插點問線,插線問點等一系列樹上的問題 假如現在給你一棵樹,然後沒兩條邊之間有一條權值,有一些操作,1:x---y之間的最大權值是多少,2:改變x--

【Linux】程序間通訊(IPC)之訊息佇列測試用例

學習環境 Centos6.5 Linux 核心 2.6 什麼是訊息佇列? 訊息佇列是SystemV版本中三種程序通訊機制之一,另外兩種是訊號量和共享儲存段。訊息佇列提供了程序間傳送資料塊的方法,而且每個資料塊都有一個型別標識。訊息佇列是基於訊息的,而管

keras之ImageDataGenerator引數用法例項-01

keras圖片生成器ImageDataGenerator keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,     samplewise_center=False,   &nbs

Spring中@Async用法簡單例項

Spring中@Async用法 引言: 在Java應用中,絕大多數情況下都是通過同步的方式來實現互動處理的;但是在處理與第三方系統互動的時候,容易造成響應遲緩的情況,之前大部分都是使用多執行緒來完成此類任務,其實,在spring 3.x之後,就已經內建了@Async來完美解決這個問題,本文將完成

Oracle列轉行函式 Listagg() 語法應用例項

工作中用到一段比較複雜的SQL查詢指令碼,使用了listagg()函式實現了具有多個值的欄位的填充(即,列表聚合,list aggregation(我猜的))。說簡單點,listagg()函式可以實現多列記錄聚合為一條記錄,從而實現資料的壓縮、緻密化(data densifi

Excel資料分析與業務建模_第四章_匹配函式MATCH(語法應用例項

如果有一天,EXCEL中沒有了LOOKUP函式,怎麼辦?答案是就靠MATCH和INDEX兩兄弟了。 MATCH函式可返回指定區域內指定內容所在的行號(縱向區域)或列號(橫向區域)。 Suppose you have a worksheet with 5,000 rows c

【Linux】程序間通訊-訊號量程式設計例項

前面一篇文章執行緒同步之訊號量同步 講的是執行緒之間的訊號量,這篇講的更加具有通用性,能夠實現程序之間的同步。 訊號量概述 訊號量定義: 它是一個特殊變數,只允許對它進行等待和傳送訊號這兩種操作。 P(訊號量變數sv):等待。如果sv大於0,減小sv。如果sv為0,掛起這

程序間通訊--訊號量程式設計例項

訊號量概述 訊號量定義: 它是一個特殊變數,只允許對它進行等待和傳送訊號這兩種操作。 P(訊號量變數sv):等待。如果sv大於0,減小sv。如果sv為0,掛起這個程序的執行。V(訊號量變數sv):傳送訊號。如果有程序被掛起等待sv,使其恢復執行。如果沒有進行被掛起等待sv

Oracle INSTR函式(子字串查詢)語法應用例項

 據說以下這道看似簡單的問題可以測試Oracle查詢的能力: 問題: 答案: select c.ci_id,wm_concat(s.stu_name) from pm_ci c,pm_stu s where instr(c.stu_ids,s.stu_

NAT技術配置例項

Outside local address:外部本地地址,不必是合法地址。當外部網路資料到達內部網路,外部網路中的主機IP地址與內部網路中的主機處在同一網段時,為防止內部主機誤認外部主機與自己在同一網段而廣播ARP請求,造成無法通訊,將外部主機的地址轉換成外部本地地址之後再與內部主機進行通訊。

IOS 檔案讀寫操作簡單例項

iPhone 檔案讀寫操作1,寫檔案操作- (IBAction)btnWrite:(id)sender { //建立檔案管理器 NSFileManager *fileManager = [NSFileManager defaultManager]; //獲取路徑

shell 程式設計 for 迴圈應用例項

與其他程式語言類似,Shell支援for迴圈。for迴圈一般格式為:for 變數 in 列表do    command1    command2    ...    commandNdone列表是一組值(數字、字串等)組成的序列,每個值通過空格分隔。每迴圈一次,就將列表中的下

程序間通訊-訊號量程式設計例項

前面一篇文章執行緒同步之訊號量同步 講的是執行緒之間的訊號量,這篇講的更加具有通用性,能夠實現程序之間的同步。 訊號量概述 訊號量定義: 它是一個特殊變數,只允許對它進行等待和傳送訊號這兩種操作。 P(訊號量變數sv):等待。如果sv大於0,減小sv。如果sv為0,掛

技術之ILP應用

區塊鏈;跨鏈;托管;ilp;rippleAbstract:As the booming of BlockChain technology, the requirement of asset transfer between different ledgers is as imperative as possi

機器學習中的概率模型和概率密度估計方法VAE生成模型之二(作者簡介)

AR aca rtu href beijing cert school start ica Brief Introduction of the AuthorChief Architect at 2Wave Technology Inc. (a startup company

機器學習中的概率模型和概率密度估計方法VAE生成模型之一(簡介)

價值 新書 The aar 生成 syn TE keras 第一章 A Gentle Introduction to Probabilistic Modeling and Density Estimation in Machine LearningAndA Detailed

機器學習中的概率模型和概率密度估計方法VAE生成模型之五(第3章 之 EM算法)

ado vpd dea bee OS deb -o blog Oz 機器學習中的概率模型和概率密度估計方法及VAE生成式模型詳解之五(第3章 之 EM算法)

機器學習中的概率模型和概率密度估計方法VAE生成模型之六(第3章 之 VI/VB算法)

dac term http 51cto -s mage 18C watermark BE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

機器學習中的概率模型和概率密度估計方法VAE生成模型之七(第4章 之 梯度估算)

.com 概率 roc 生成 詳解 time 學習 style BE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?機器學習中的概率模型和概率密度估計方法及V