1. 程式人生 > >Deque (雙端佇列)介紹,附原始碼

Deque (雙端佇列)介紹,附原始碼

Deque,為雙端操作佇列。約定在隊頭的進出操作為push和pop, 在隊尾進出操作為inject和eject。每個節點存在Data, Next, Last分別指資料, 下一個, 上一個。而對於多個節點組成的佇列, 存在Front和Rear分別指隊頭和隊尾。詳細定義見原始碼。 Push和Pop操作在隊頭進行, D->Front->Next為第一個資料,Push將新的節點p插入D->Front->Next前, 即三個主要節點順序為D->Front p D->Front->Next, D->Front 為p的Last, D->Front->Next 為p的Next, D->Front->Next為p。Pop將D->Front->Next彈出, D->Front->Next置為D->Front->Next->Next。 Inject和Eject則在隊尾進行, 與D->Front不同的是, 在Inject後, D->Rear將不再是最後一個, 即p->Last = D->Rear。
#include <stdio.h>
#include <stdlib.h>

#define ElementType int
#define ERROR 1e5
typedef enum { push, pop, inject, eject, end } Operation;

typedef struct Node *PtrToNode;
struct Node {
	ElementType Element;
	PtrToNode Next, Last;//Last指上一個
};
typedef struct DequeRecord *Deque;
struct DequeRecord {
	PtrToNode Front, Rear;
};
Deque CreateDeque();
int Push(ElementType X, Deque D);
ElementType Pop(Deque D);
int Inject(ElementType X, Deque D);
ElementType Eject(Deque D);

Operation GetOp();          /* details omitted */
void PrintDeque(Deque D); /* details omitted */

int main()
{
	ElementType X;
	Deque D;
	int done = 0;

	D = CreateDeque();
	while (!done) {
		switch (GetOp()) {
		case push:
			scanf("%d", &X);
			if (!Push(X, D)) printf("Memory is Full!\n");
			break;
		case pop:
			X = Pop(D);
			if (X == ERROR) printf("Deque is Empty!\n");
			break;
		case inject:
			scanf("%d", &X);
			if (!Inject(X, D)) printf("Memory is Full!\n");
			break;
		case eject:
			X = Eject(D);
			if (X == ERROR) printf("Deque is Empty!\n");
			break;
		case end:
			PrintDeque(D);
			done = 1;
			break;
		}
	}
	return 0;
}


Deque CreateDeque()
{
	Deque q = (Deque)malloc(sizeof(*(Deque)NULL));
	q->Front = (PtrToNode)malloc(sizeof(*(PtrToNode)NULL));
	q->Front->Last = q->Front->Next = NULL;
	q->Rear = q->Front;
	return q;
}

int Push(ElementType X, Deque D)
{
	PtrToNode p;
	p = (PtrToNode)malloc(sizeof(*(PtrToNode)NULL));
	if (p == NULL) return 0; //Verify 
	p->Element = X;
	p->Last = D->Front; //結點p的Last 指向D的前端, 將p置於隊頭
	p->Next = D->Front->Next;
	D->Front->Next = p;
	if (D->Rear == D->Front)	D->Rear = p;
	else p->Next->Last = p;
	return 1;
}

ElementType Pop(Deque D)
{
	if (D->Front == D->Rear)	return ERROR;
	ElementType e;
	PtrToNode p = D->Front->Next;
	e = p->Element;
	D->Front->Next = p->Next;
	if (p->Next)	D->Front->Next->Last = D->Front;
	else D->Rear = D->Front;
	free(p);
	return e;
}

int Inject(ElementType X, Deque D)
{
	PtrToNode p;
	p = (PtrToNode)malloc(sizeof(*(PtrToNode)NULL));
	if (p == NULL) return 0;
	p->Element = X;
	p->Last = D->Rear;
	p->Next = NULL;
	D->Rear->Next = p;
	D->Rear = p;
	return 1;
}

ElementType Eject(Deque D)
{
	if (D->Front == D->Rear)	return ERROR;
	ElementType e;
	PtrToNode p = D->Rear;
	e = p->Element;
	p->Last->Next = NULL;
	D->Rear = p->Last;
	free(p);
	return e;
}