1. 鏈表
鏈表可以使用數組實現,也可以使用指標實現。用數組實現的鏈表的插入、刪除操作需要O(N)的時間複雜度,很少使用。
用指標實現的鏈表,插入刪除操作可以O(1)時間完成。
Code
鏈表結點定義
struct Node
{
ElementType Element;
Node* Next;
};
鏈表常用操作
int IsEmpty(Node* L);
int IsLast(Node* L);
Node* Find(ElementType X, Node* L);
Node* FindPrevious(ElementType X, Node* L);
void Delete(ElementType X, Node* L);
void Insert(ElementType X, Node* L, Node* P);
2. 棧
棧是插入刪除操作都只能在一個位置上進行的表,該位置是表的末端,叫做頂。棧可以用數組實現,也可以用單鏈表。
Code
結點定義
struct Node
{
ElementType Element;
Node* Next;
};
常用操作:鏈表實現的棧,入棧出棧操作就在表頭進行。
int IsEmpty(Node* S);
void Push(ElementType Element, Node* S);
ElementType Top(Node* S);
void Pop(Node* S);
棧的數組實現是一種更為流行的實現方式
struct Stack
{
int Capacity;
int TopOfStack;
ElementType *Array;
};
void Push(ElementType X, Stack* S)
{
if(!IsFull(S))
Error("Full stack");
else
S->Array[++S->TopOfStack]=X;
}
3. 隊列
隊列也是表,使用隊列時插入在一端進行而刪除則在另一端進行。使用迴圈數組實現。當隊列為空白時,size=0。
Code
結點定義
struct Queue
{
int Capacity;
int Front;
int Rear;
int Size;
ElementType *Array;
};
IsEmpty(Queue* Q);
//迴圈數組的size=Rear-Front+n*Capacity,n取能使0<size<Capacity的那一個
void Enqueue(ElementType X,Queue* Q)
{
if(!IsFull(Q))
Error("Full Queue");
else
{
Q->size++;
if(Q->Capacity-Q->Rear==1)
Q->Rear=0;
else
Q->Rear++;
Q->Array[Q->Rear]=X;
}
}
void Dequeue(Queue* Q);
4. 二叉尋找樹
完全二叉樹:若設二叉樹的高度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的節點都連續集中在最左邊,這就是完全二叉樹。
滿二叉樹:除最後一層外,每一層上的所有結點都有兩個子結點(最後一層上的結點為葉子結點)。也可以這樣理解,除葉子結點外的所有結點均有兩個子結點。
對於樹中的每個結點X,它的左子樹中所有關鍵字的值都小於X的關鍵字值,而它的右子樹中所有關鍵字值大於X的關鍵字值。二叉樹不一定是完全樹,堆才是完全樹。
Code
結點定義
struct Node
{
ElementType Element;
Node* Left;
Node* Right;
};
常用操作
Node* Find(ElementType X,Node* T); //重點掌握非遞迴演算法
Node* Find(ElementType X,Node* T)
{
if(T==NULL)
Return NULL;
while(T!=NULL)
{
if(T->Element==X)
return T;
else if(T->Element>X)
T=T->Left;
else if(T->Element<X)
T=T->Right;
else
return NULL;
}
}
Node* FindMin(Node* T);
Node* FindMax(Node* T);
Node* Insert(ElementType X,Node* T);//Insert略簡單,可以使用遞迴實現
Node* Insert(ElementType X,Node* T)
{
if(T==NULL)
T=malloc(sizeof(struct Node));
if(T==NULL)
Error("Out of space!");
else
{
T->Element=X;
T->Left=T->Right=0;
}
else
if(X<T->Element)
T->Left=Insert(X,T->Left);
else
if(X>T->Right)
T->Right=Insert(X,T->Right);
return T;
}
Node* Delete(ElementType X,Node* T);//刪除略複雜,需要考慮是葉子節點,還是有幾個孩子節點的情況,還涉及到找最小子結點移動到刪除的父節點。
AVL樹:一棵AVL樹是其每個結點的左子樹和右子樹的高度最多差1的二叉尋找樹。
5. 堆
堆有兩個性質,即結構性和堆序性。
結構性:堆是一棵被完全填滿的二叉樹,有可能的例外是在底層,底層上的元素從左至右填入。堆用數組實現,數組下標為0的元素不存資料,從下標1開始。對於數組任一位置i上的元素,其左兒子在位置2i上,右兒子在左兒子後的單元[2i+1]中,它的父親則在位置[i/2]
堆序性:在每一個堆中,對於每個節點X,X的父親中的關鍵字小於(或等於)X中的關鍵字,根節點除外。這個是對於小頂堆。
代碼
堆結構定義
struct HeapStruct
{
int Capacity;
int size;
ElementType *Elements;
};
堆常用操作
void Insert(ElementType X,HeapStruct* H);//涉及到上濾
{
int i;
if(!IsFull(H))
{
Error("PriorityQueue is full.");
return;
}
for(i=++H->size;H->Elements[i/2]>X;i/=2)
H->Elements[i]=H->Elements[i/2];
H->Elements[i]=X;
}
ElementType DeleteMin(HeapStruct* H);//複雜,暫時不掌握了
ElementType FindMin(HeapStruct* H);
int IsFull(HeapStruct* H);
int IsEmpty(HeapStruct* H);