㈠ 圖的存儲結構——所存儲的信息有哪些
一、鄰接矩陣存儲方法
鄰接矩陣是表示頂點之間相鄰關系的矩陣。
設G=(V,E)是具有n(n>0)個頂點的圖,頂點的順序依次為0~n-1,則G的鄰接矩陣A是n階方陣,其定義如下:
(1)如果G是無向圖,則:
A[i][j]=1:若(i,j)∈E(G) 0:其他
(2)如果G是有向圖,則:
A[i][j]=1:若<i,j>∈E(G) 0:其他
(3)如果G是帶權無向圖,則:
A[i][j]= wij :若i≠j且(i,j)∈E(G) 0:i=j ∞:其他
(4)如果G是帶權有向圖,則:
A[i][j]= wij :若i≠j且<i,j>∈E(G) 0:i=j∞:其他
注意:帶權圖和不帶權圖表示的元素類型不同。
帶權圖(不論有向還是無向圖)A[i][j]用double表示,不帶權圖(不論有向還是無向圖)A[i][j]用int表示。
用一維數組G[ ]存儲有4個頂點的無向圖如:G[ ] = { 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 }
則頂點2和頂點0之間是有邊的。
如:
鄰接矩陣的特點如下:
(1)圖的鄰接矩陣表示是唯一的。
(2)無向圖的鄰接矩陣一定是一個對稱矩陣。因此,按照壓縮存儲的思想,在具體存放鄰接矩陣時只需存放上(或下)三角形陣的元素即可。
(3)不帶權的有向圖的鄰接矩陣一般來說是一個稀疏矩陣。因此,當圖的頂點較多時,可以採用三元組表的方法存儲鄰接矩陣。
(4)對於無向圖,鄰接矩陣的第i行(或第i列)非零元素(或非∞元素)的個數正好是第i個頂點的度。
(5)對於有向圖,鄰接矩陣的第i行(或第i列)非零元素(或非∞元素)的個數正好是第i個頂點的出度(或入度)。
(6)用鄰接矩陣方法存儲圖,很容易確定圖中任意兩個頂點之間是否有邊相連。但是,要確定圖中有多少條邊,則必須按行、按列對每個元素進行檢測,所花費的時間代價很大。這是用鄰接矩陣存儲圖的局限性。
鄰接矩陣的數據類型定義如下:
#define MAXV <最大頂點個數>
typedef struct
{ int no; //頂點編號
InfoType info; //頂點其他信息
} VertexType; //頂點類型
typedef struct //圖的定義
{ int edges[MAXV][MAXV]; //鄰接矩陣
int n,e; //頂點數,弧數
VertexType vexs[MAXV]; //存放頂點信息
} MGraph; //圖的鄰接矩陣表示類型
二、 鄰接表存儲方法
圖的鄰接表存儲方法是一種順序分配與鏈式分配相結合的存儲方法。
在鄰接表中,對圖中每個頂點建立一個單鏈表,第i個單鏈表中的節點表示依附於頂點i的邊(對有向圖是以頂點i為尾的邊)。每個單鏈表上附設一個表頭節點。
其中,表節點由三個域組成,adjvex指示與頂點i鄰接的點在圖中的位置,nextarc指示下一條邊或弧的節點,info存儲與邊或弧相關的信息,如權值等。
表頭節點由兩個域組成,data存儲頂點i的名稱或其他信息,firstarc指向鏈表中第一個節點。
typedef struct ANode
{ int adjvex; //該邊的終點編號
struct ANode *nextarc; //指向下一條邊的指針
InfoType info; //該邊的相關信息
} ArcNode; //邊表節點類型
typedef struct Vnode
{ Vertex data; //頂點信息
ArcNode *firstarc; //指向第一條邊
} VNode; //鄰接表頭節點類型
typedef VNode AdjList[MAXV]; //AdjList是鄰接表類型
typedef struct
{ AdjList adjlist; //鄰接表
int n,e; //圖中頂點數n和邊數e
} ALGraph; //完整的圖鄰接表類型
鄰接表的特點如下:
(1)鄰接表表示不唯一。這是因為在每個頂點對應的單鏈表中,各邊節點的鏈接次序可以是任意的,取決於建立鄰接表的演算法以及邊的輸入次序。
(2)對於有n個頂點和e條邊的無向圖,其鄰接表有n個頂點節點和2e個邊節點。顯然,在總的邊數小於n(n-1)/2的情況下,鄰接表比鄰接矩陣要節省空間。
(3)對於無向圖,鄰接表的頂點i對應的第i個鏈表的邊節點數目正好是頂點i的度。
(4)對於有向圖,鄰接表的頂點i對應的第i個鏈表的邊節點數目僅僅是頂點i的出度。其入度為鄰接表中所有adjvex域值為i的邊節點數目。
例, 給定一個具有n個節點的無向圖的鄰接矩陣和鄰接表。
(1)設計一個將鄰接矩陣轉換為鄰接表的演算法;
(2)設計一個將鄰接表轉換為鄰接矩陣的演算法;
(3)分析上述兩個演算法的時間復雜度。
解:
(1)在鄰接矩陣上查找值不為0的元素,找到這樣的元素後創建一個表節點並在鄰接表對應的單鏈表中採用前插法插入該節點。
void MatToList(MGraph g,ALGraph *&G)
//將鄰接矩陣g轉換成鄰接表G
{ int i,j,n=g.n; ArcNode *p; //n為頂點數
G=(ALGraph *)malloc(sizeof(ALGraph));
for (i=0;i<n;i++) //給所有頭節點的指針域置初值
G->adjlist[i].firstarc=NULL;
for (i=0;i<n;i++) //檢查鄰接矩陣中每個元素
for (j=n-1;j>=0;j--)
if (g.edges[i][j]!=0)
{ p=(ArcNode *)malloc(sizeof(ArcNode));
//創建節點*p
p->adjvex=j;
p->nextarc=G->adjlist[i].firstarc;
//將*p鏈到鏈表頭
G->adjlist[i].firstarc=p;
}
G->n=n;G->e=g.e;
}
(2)在鄰接表上查找相鄰節點,找到後修改相應鄰接矩陣元素的值。
void ListToMat(ALGraph *G,MGraph &g)
{ int i,j,n=G->n;ArcNode *p;
for (i=0;i<n;i++)
{ p=G->adjlist[i].firstarc;
while (p!=NULL)
{ g.edges[i][p->adjvex]=1;
p=p->nextarc;
}
}
g.n=n;g.e=G->e;
}
(3)演算法1的時間復雜度均為O(n2)。演算法2的時間復雜度為O(n+e),其中e為圖的邊數。
㈡ 圖的存儲結構
鄰接矩陣:
有向圖的鄰接矩陣
具有n個頂點的有向圖可以用一個n′n的方形矩陣表示。假設該矩陣的名稱為M,則當<vi,vj>是該有向圖中的一條弧時,M[i,j]=1;否則M[i,j]=0。第i個頂點的出度為矩陣中第i行中"1"的個數;入度為第i列中"1"的個數,並且有向圖弧的條數等於矩陣中"1"的個數。
無向圖的鄰接矩陣
具有n個頂點的無向圖也可以用一個n′n的方形矩陣表示。假設該矩陣的名稱為M,則當(vi,vj)是該無向圖中的一條邊時,M[i,j]=M[j,i]=1;否則,M[i,j]=M[j,j]=0。第i個頂點的度為矩陣中第i 行中"1"的個數或第i列中"1"的個數。圖中邊的數目等於矩陣中"1"的個數的一半,這是因為每條邊在矩陣中描述了兩次。
在C 語言中,實現鄰接矩陣表示法的類型定義如下所示: #defineMAX_VERTEX_NUM20typedefstructgraph{Elemtypeelem[MAX_VERTEX_NUM][MAX_VERTEX_NUM];intn;}Graph;鄰接表
邊結點的結構為:
adjvex是該邊或弧依附的頂點在數組中的下標,next是指向下一條邊或弧結點的指針
elem是頂點內容,firstedge是指向第一條邊或弧結點的指針。
在C語言中,實現鄰接表表示法的類型定義如下所示: #defineMAX_VERTEX_NUM30//最大頂點個數typestructEdgeLinklist{//邊結點intadjvex;structEdgeLinklist*next;}EdgeLinklist;typedefstructVexLinklist{//頂點結點Elemtypeelem;EdgeLinklist*firstedge;}VexLinklist,AdjList[MAX_VERTEX_NUM];創建有向圖和無向圖鄰接表的演算法實現:
(1) 創建有向圖鄰接表 voidCreate_adj(AdjListadj,intn){for(i=0;i<n;i++){//初始化頂點數組scanf(&adj.elem);adj.firstedge=NULL;}scanf(&i,&j);//輸入弧while(i){s=(EdgeLinklist*)malloc(sizeof(EdgeLinklist));//創建新的弧結點s->adgvex=j-1;s->next=adj[i-1].firstedge;//將新的弧結點插入到相應的位置adj[i-1].firstegde=s;scanf(&i,&j);//輸入下一條弧}}(2)創建無向圖的鄰接表 voidCreate_adj(AdjListadj,intn){for(i=0;i<n;i++){//初始化鄰接表scanf(&adj.elem);adj.firstedge=NULL;}scanf(&i,&j);//輸入邊while(i){s1=(EdgeLinklist*)malloc(sizeof(EdgeLinklist));s1->adgvex=j-1;s2=(EdgeLinklist*)malloc(sizeof(EdgeLinklist));s2->adgvex=i-1;s1->next=adj[i-1].firstedge;adj[i-1].firstegde=s1;s2->next=adj[j-1].firstedge;adj[j-1].firstegde=s2;scanf(&i,&j);}}
㈢ 用鄰接表表示圖的廣度優先搜索時的存儲結構,通常採用()結構來實現演算法
B。
廣度優先搜索相當於層次遍歷,深度優先搜索相當於先序優先遍歷,所以答案選擇B。
鄰接表表示的圖的廣度優先搜索一般採用隊列結構來實現演算法:
首先選擇一個起始節點,把它的臨界表中節點加入到隊列中,每次取出隊首元素,然後把該元素的鄰接表中的節點加入到隊列末尾,標記已遍歷過的節點,直到隊列中沒有節點為止,一般棧用於深度優先搜索,隊列用於廣度優先搜索。
(3)圖文存儲結構演算法擴展閱讀:
深度優先搜索用一個數組存放產生的所有狀態。
(1) 把初始狀態放入數組中,設為當前狀態;
(2) 擴展當前的狀態,產生一個新的狀態放入數組中,同時把新產生的狀態設為當前狀態;
(3) 判斷當前狀態是否和前面的重復,如果重復則回到上一個狀態,產生它的另一狀態;
(4) 判斷當前狀態是否為目標狀態,如果是目標,則找到一個解答,結束演算法。
㈣ 採用順序存儲方法和鏈式存儲方法分別畫出圖6.1所示二叉樹的存儲結構。【在線等】
線性是線性,順序是順序,線性是邏輯結構,順序是儲存結構,兩者不是一個概念。線性是指一個節點只有一個子節點,而樹,或二叉樹一個節點後有多個子節點,且子節點不能相互聯系。
順序存儲可能會浪費空間(在非完全二叉樹的時候),但是讀取某個指定的節點的時候效率比較高。
鏈式存儲相對二叉樹比較大的時候浪費空間較少,但是讀取某個指定節點的時候效率偏低。
二叉樹的順序存儲,尋找後代節點和祖先節點都非常方便,但對於普通的二叉樹,順序存儲浪費大量的存儲空間,同樣也不利於節點的插入和刪除。因此順序存儲一般用於存儲完全二叉樹。
鏈式存儲相對順序存儲節省存儲空間,插入刪除節點時只需修改指針,但回尋找指定節點時很不方便。不過普通答的二叉樹一般是用鏈式存儲結構。
(4)圖文存儲結構演算法擴展閱讀:
(1)完全二叉樹——若設二叉樹的高度為h,除第h層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層有葉子結點,並且葉子結點都是從左到右依次排布,這就是完全二叉樹。
(2)滿二叉樹——除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹。
(3)平衡二叉樹——平衡二叉樹又被稱為AVL樹(區別於AVL演算法),它是一棵二叉排序樹,且具有以下性質:是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。
二叉樹是樹的一種特殊情形,是一種更簡單而且應用更加廣泛的樹。
㈤ 資料庫技術知識數據結構的演算法
資料庫技術知識數據結構的演算法
對於將要參加計算機等級考試的考生來說,計算機等級考試的知識點輔導是非常重要的復習資料。以下是我收集的資料庫技術知識數據結構的演算法,希望大家認真閱讀!
1、數據:數據的基本單位是數據元素。數據元素可由一個或多個數據項組成。數據項是數據的不可分割的最小單位
2、數據結構:數據的邏輯結構、數據的存儲結構、數據的運算
3、主要的數據存儲方式:順序存儲結構(邏輯和物理相鄰,存儲密度大)和鏈式存儲結構
順序存儲結構:
順序存儲計算公式 Li=L0+(i-1)×K 順序結構可以進行隨機存取;插人、刪除運算會引起相應節點的大量移動
鏈式存儲結構:a、指針域可以有多個,可以指向空,比比順序存儲結構的存儲密度小
b、邏輯上相鄰的節點物理上不一定相鄰。 c、插人、刪除等不需要大量移動節點
4、順序表:一般情況下,若長度為n的順序表,在任何位置插入或刪除的概率相等,元素移動的平均次數為n/2(插入)和(n-1)/2(刪除)。
5、鏈表:線性鏈表(單鏈表和雙向鏈表等等)和非線性鏈表
線性鏈表也稱為單鏈表,其每個一節點中只包含一個指針域,雙鏈表中,每個節點中設置有兩個指針域。(注意結點的插入和刪除操作)
6、棧:“後進先出”(LIFO)表。棧的應用:表達式求解、二叉樹對稱序周遊、快速排序演算法、遞歸過程的實現等
7、隊列:“先進先出”線性表。應用:樹的層次遍歷
8、串:由零個或多個字元組成的有限序列。
9、多維數組的順序存儲:
10、稀疏矩陣的存儲:下三角矩陣順序存儲
其他常見的存儲方法還有三元組法和十字鏈表法
11、廣義表:由零個或多個單元素或子表所組成的有限序列。廣義表的元素可以是子表,而子表的元素還可以是子表
12、樹型結構:非線性結構。常用的樹型結構有樹和二叉樹。
二叉樹與樹的區別:二叉樹不是樹的特殊情況,樹和二叉樹之間最主要的區別是:二叉樹的節點的子樹要區分左子樹和右子樹,即使在節點只有一棵子樹的情況下也要明確指出該子樹是左子樹還是右子樹。
13、樹(森林)與二叉樹之間的轉換(要會轉換)
14、二叉樹和樹的周遊(遍歷)
二叉樹的周遊主要有以下3種方式:前序法(NLR)、對稱序法(LNR)、後序法(LRN)
周遊樹和樹林:深度優先和按廣度優先兩種方式進行。深度優先方式又可分為按先根次序和按後根次序周遊
樹與二叉樹周遊之間的對應關系:按先根次序周遊樹正好與按前序法周遊樹對應的二叉樹等同,後根次序周遊樹正好與按對稱序法周遊對應的`二叉樹等同
按廣度優先方式就是層次次序周遊
15、二叉樹的存儲和線索
二叉樹的存儲結構:二叉樹的llink一rlink法存儲表示
線索二叉樹:在有n個節點的二叉樹的且llink - rlink法存儲表示中,必定有n+1個空指針域
16、哈夫曼樹:一類帶權路徑長度最短的樹。樹的帶權路徑長度為樹中所有葉子節點的帶權路徑長度之和WPL。
17、查找:
(1)順序查找:平均查找長度為(n +1 )/2次,時間復雜度為O(n)
(2)二分法查找:線性表節點必須按關鍵碼值排序,且線性表是以順序存儲方式存儲的。查找成功比較次數log2n,查找失敗比較次數log2n+1
(3)分塊查找:先是塊間查找,然後塊內查找。
(4)散列表(哈希表Hash)的存儲和查找:處理沖突的方法:開地址法(線性探測法)、拉鏈法等
負載因子(裝填因子)=表實際存儲的結點個數/表的最大能存儲結點個數(即表長)
二叉排序樹:每個結點左子樹的所有關鍵碼值都小於該結點關鍵碼值,右子樹所有結點關鍵碼值都大於該結點關鍵碼值。對稱周遊二叉排序樹,得到一個有序序列,時間復雜度O(log2n)
B樹和B+樹:M階樹,每個結點至多有M-1個關鍵碼,至少有M/2(取上界)-1個關鍵碼。B樹適合隨機查找,不適合順序查找。B+樹適合順序查找。
18、排序
直接插人排序、希爾排序、直接選擇排序、堆排序、起泡排序、快速排序等排序演算法要了解。
直接選擇排序、希爾排序、快速排序和堆排序是不穩定排序,其他排序為穩定排序
;㈥ 數據的存儲結構及數據的運算之間存在著怎樣的關系
需要達到<識記>層次的基本概念和術語有:數據、數據元素、數據項、數據結構。特別是數據結構的邏輯結構、存儲結構及數據運算的含義及其相互關系。數據結構的兩大類邏輯結構和四種常用的存儲表示方法。
需要達到<領會>層次的內容有演算法、演算法的時間復雜度和空間復雜度、最壞的和平均時間復雜度等概念,演算法描述和演算法分析的方法、對一般的演算法要能分析出時間復雜度。對於基本概念,仔細看書就能夠理解,這里簡單提一下:數據就是指能夠被計算機識別、存儲和加工處理的信息的載體。數據元素是數據的基本單位,有時一個數據元素可以由若干個數據項組成。數據項是具有獨立含義的最小標識單位。如整數這個集合中,10這個數就可稱是一個數據元素.又比如在一個資料庫(關系式資料庫)中,一個記錄可稱為一個數據元素,而這個元素中的某一欄位就是一個數據項。數據結構的定義雖然沒有標准,但是它包括以下三方面內容:邏輯結構、存儲結構、和對數據的操作。這一段比較重要,我用自己的語言來說明一下,大家看看是不是這樣。
比如一個表(資料庫),我們就稱它為一個數據結構,它由很多記錄(數據元素)組成,每個元素又包括很多欄位(數據項)組成。那麼這張表的邏輯結構是怎麼樣的呢? 我們分析數據結構都是從結點(其實也就是元素、記錄、頂點,雖然在各種情況下所用名字不同,但說的是同一個東東)之間的關系來分析的,對於這個表中的任一個記錄(結點),它只有一個直接前趨,只有一個直接後繼(前趨後繼就是前相鄰後相鄰的意思),整個表只有一個開始結點和一個終端結點,那我們知道了這些關系就能明白這個表的邏輯結構了。
而存儲結構則是指用計算機語言如何表示結點之間的這種關系。如上面的表,在計算機語言中描述為連續存放在一片內存單元中,還是隨機的存放在內存中再用指針把它們鏈接在一起,這兩種表示法就成為兩種不同的存儲結構。(注意,在本課程里,我們只在高級語言的層次上討論存儲結構。) 第三個概念就是對數據的運算,比如一張表格,我們需要進行查找,增加,修改,刪除記錄等工作,而怎麼樣才能進行這樣的操作呢? 這也就是數據的運算,它不僅僅是加減乘除這些算術運算了,在數據結構中,這些運算常常涉及演算法問題。
弄清了以上三個問題,就可以弄清數據結構這個概念。
㈦ 圖的五種存儲結構
圖的鄰接矩陣(Adjacency Matrix): 圖的鄰接矩陣用兩個數組來表示圖。一個一維數組存儲圖中頂點信息,另一個二維數組(一般稱之為鄰接矩陣)來存儲圖中的邊或者弧的信息。從鄰接矩陣中我們自然知道一個頂點的度(對於無向圖)或者有向圖中一個頂點的入度出度信息。
假設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣。
1.對於如果圖上的每條邊不帶權值來說,那麼我們就用真(一般為1)和假(一般為0)來表示一個頂點到另一個頂點存不存在邊。下面是一個圖的鄰接矩陣的定義:
鄰接矩陣法實現帶權值的無向圖的創建如下:
按照如圖輸入各邊(不重復)
測試程序如下:
結果可得該矩陣,證明創建樹成功。 假設n個頂點e條邊的創建,createGraph演算法的時間復雜度為O(n+n*n+e)。如果需要創建一個有向圖,那麼和上面一樣一個一個錄入邊下標和權值。
鄰接矩陣這種存儲結構的優缺點: 缺點是對於邊數相對頂點較少的稀疏圖來說會存在極大的空間浪費。假設有n個頂點,優點是對於有向完全圖和無向完全圖來說鄰接矩陣是一種不錯的存儲結構,浪費的話也只浪費了n個頂點的容量。
在樹的存儲結構一節中我們提到對於孩子表示法的第三種:用一段連續的存儲單元(數組)存儲樹中的所有結點,利用一個單鏈表來存儲數組中每個結點的孩子的信息。對於圖的存儲結構來說,我們也可以利用這種方法實現圖的存儲
鄰接表(Adjacency List): 這種數組與鏈表相結合的存儲方法叫做鄰接表。1.為什麼不也用單鏈表存儲圖的結點信息呢?原因就是數組這種順序存儲結構讀取結點信息速率快。對於頂點數組中,每個數據元素還需要存儲一個指向第一個鄰接頂點的指針,這樣才可以查找邊的信息2.圖中每個頂點Vi(i > 0)的所有鄰接點構成一個線性表 (在無向圖中這個線性表稱為Vi的邊表,有向圖中稱為頂點作為弧尾的出邊表) ,由於鄰接點的不確定性,所以用鏈表存儲,有多少個鄰接點就malloc一個空間存儲鄰接點,這樣更不會造成空間的浪費(與鄰接矩陣相比來說)。3.對於鄰接表中的某個頂點來說,用戶關心的是這個頂點的鄰接點,完全可以遍歷用單鏈表設計成的邊表或者出邊表得到,所以沒必要設計成雙鏈表。
鄰接表的存儲結構:
假設現在有一無向圖G,如下圖:
從鄰接表結構中,知道一個頂點的度或者判斷兩個頂點之間是否存在邊或者求一個頂點的所有鄰接頂點是很容易的。
假設現在有一有向圖G,如下圖:
無向圖的鄰接表創建示例如下:
假設在上圖(無向圖)中的V0V1V2V3頂點值為ABCD,則依據下面測試程序可得結果:
鄰接表的優缺點: 優點是:鄰接表存儲圖,既能夠知道一個頂點的度和頂點的鄰接結點的信息,並且更不會造成空間的浪費。缺點是鄰接表存儲有向圖時,如果關心的是頂點的出度問題自然用鄰接表結構,但是想了解入度需要遍歷圖才知道(需要考慮逆鄰接表)。
十字鏈表(Orthogonal List) :有向圖的一種存儲方法,它把鄰接表和逆鄰接表結合起來,因此在十字鏈表結構中可以知道一個頂點的入度和出度情況。
重新定義頂點表的結點如下圖:
現在有一有向圖如下圖:
則它的存儲結構示意圖為:
其定義如下:
十字鏈表是用來存儲有向圖的,這樣可以看出一個頂點的出入度信息。對於無向圖來說完全沒必要用十字鏈表來存儲。
在無向圖中,因為我們關注的是頂點的信息,在考慮節約空間的情況下我們利用鄰接表來存儲無向圖。但是如果我們關注的是邊的信息,例如需要刪除某條邊對於鄰接表來說是挺繁瑣的。它需要操作兩個單鏈表刪除兩個結點。因此我們仿照十字鏈表的方式對邊表結點結構重新定義如下圖:
它的鄰接多重表結構為:
多重鄰接表的優點:對於邊的操作相比於鄰接表來說更加方便。比如說我們現在需要刪除(V0,V2)這條邊,只需將69步驟中的指針改為nullptr即可。
邊集數組(edgeset array): 邊集數組是由兩個數組組成,一個存儲頂點信息,另一個存儲邊的信息,這個邊數組中的每個數據元素由起點下標,終點下標,和權組成(如果邊上含有權值的話)。
邊數組結構如下圖:
邊集數組實現圖的存儲的優缺點:優點是對於邊的操作方便快捷,操作的只是數組元素。比如說刪除某條邊,只需要刪除一個數組元素。缺點是:對於圖的頂點信息,我們只有遍歷整個邊數組才知道,這個費時。因此對於關注邊的操作來說,邊集數組更加方便。
㈧ 海量數據存儲結構和演算法
下面的存儲過程不僅含有分頁方案,還會根據頁面傳來的參數來確定是否進行數據總數統計。
-- 獲取指定頁的數據
CREATE PROCEDURE pagination3
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) = '*', -- 需要返回的列
@fldName varchar(255)='', -- 排序的欄位名
@PageSize int = 10, -- 頁尺寸
@PageIndex int = 1, -- 頁碼
@doCount bit = 0, -- 返回記錄總數, 非 0 值則返回
@OrderType bit = 0, -- 設置排序類型, 非 0 值則降序
@strWhere varchar(1500) = '' -- 查詢條件 (注意: 不要加 where)
AS
declare @strSQL varchar(5000) -- 主語句
declare @strTmp varchar(110) -- 臨時變數
declare @strOrder varchar(400) -- 排序類型
if @doCount != 0
begin
if @strWhere !=''
set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere
else
set @strSQL = "select count(*) as Total from [" + @tblName + "]"
end
--以上代碼的意思是如果@doCount傳遞過來的不是0,就執行總數統計。以下的所有代碼都是@doCount為0的情況
else
begin
if @OrderType != 0
begin
set @strTmp = "<(select min"
set @strOrder = " order by [" + @fldName +"] desc"
--如果@OrderType不是0,就執行降序,這句很重要!
end
else
begin
set @strTmp = ">(select max"
set @strOrder = " order by [" + @fldName +"] asc"
end
if @PageIndex = 1
begin
if @strWhere != ''
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from [" + @tblName + "] where " + @strWhere + " " + @strOrder
else
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["+ @tblName + "] "+ @strOrder
--如果是第一頁就執行以上代碼,這樣會加快執行速度
end
else
begin
--以下代碼賦予了@strSQL以真正執行的SQL代碼
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "] from [" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrder
if @strWhere != ''
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
+ @fldName + "] from [" + @tblName + "] where " + @strWhere + " "
+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
end
end
exec (@strSQL)
GO
上面的這個存儲過程是一個通用的存儲過程,其注釋已寫在其中了。