1. 程式人生 > >大話資料結構,雙端迴圈連結串列,源程式

大話資料結構,雙端迴圈連結串列,源程式

在網上找了下大話資料結構這本書的原始碼,發現第三章雖然有說到雙端連結串列卻沒給出實現,於是自己線上性連結串列的基礎上修改了一下,原始碼如下:

我將只有一個頭結點的時候,頭結點的next和prior都指向自己。

主要是注意一下插入的時候基本都遵循這個模型:,也就是找到要插入的地方的前一個數據的座標(可能是頭結點)。

#include "stdio.h"    
#include "string.h"
#include "ctype.h"      
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 20 /* 儲存空間初始分配量 */
#define RANDOMINT(m,n) ((int)(rand()%(n-m+1)+m))


typedef int Status;/* Status是函式的型別,其值是函式結果狀態程式碼,如OK等 */
typedef int ElemType;/* ElemType型別根據實際情況而定,這裡假設為int */


Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}


typedef struct DulNode
{
	ElemType data;
	struct DulNode *next;
	struct DulNode *prior;
}DulNode;
typedef struct DulNode *DuLinkList;


/* 初始化順序線性表 */
Status InitList(DuLinkList *L)
{
	if ((*L = (DuLinkList)malloc(sizeof(DulNode))) != NULL)
	{
		(*L)->next = (*L);
		(*L)->prior = (*L);
		return OK;
	}
	else return ERROR;
}

/* 初始條件:順序線性表L已存在。操作結果:若L為空表,則返回TRUE,否則返回FALSE */
Status ListEmpty(DuLinkList L)
{
	if (L->next != L)
		return FALSE;
	else
		return TRUE;
}

/* 初始條件:順序線性表L已存在。操作結果:將L重置為空表 */
Status ClearList(DuLinkList *L)
{
	DuLinkList p, q;
	q = (*L)->next;
	(*L)->next = *L;
	(*L)->prior = *L;
	while (q != *L) //首先判斷首元素是否空
	{
		p = q->next;
		free(q);
		q = p;
	}
	return OK;
}

/* 初始條件:順序線性表L已存在。操作結果:返回L中資料元素個數 */
int ListLength(DuLinkList L)
{
	int i = 0;
	DuLinkList p = L->next; /* p指向第一個結點 */
	while (p != L)
	{
		p = p->next;
		++i;
	}
	return i;
}

/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L) */
/* 操作結果:用e返回L中第i個數據元素的值 */
Status GetElem(DuLinkList L, int i, ElemType *e)
{
	if (i > ListLength(L) || i < 1 || ListLength(L) == 0)
		return ERROR;
	int j = 1;
	DuLinkList p;
	p = L->next;

	while (p!=L && j < i)
	{
		p = p->next;
		++j;
	}
	*e = p->data;
	return OK;
}

/* 初始條件:順序線性表L已存在 */
/* 操作結果:返回L中第1個與e滿足關係的資料元素的位序。 */
/* 若這樣的資料元素不存在,則返回值為0 */
int LocateElem(DuLinkList L, ElemType e)
{

	int i = 1;
	DuLinkList p = L->next;
	while (p!=L && p->data != e)
	{
		p = p->next;
		++i;
		if (i > ListLength(L))
		{
			return 0;
		}
	}
	return i;
}

/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L), */
/* 操作結果:在L中第i個位置之前插入新的資料元素e,L的長度加1 */
Status ListInsert(DuLinkList *L, int i, ElemType e)
{
	if (i < 1)
	{
		return ERROR;
	}
	int j = 0;
	DuLinkList p, q, s;
	p = (*L);
	while (j < i - 1) //這裡判斷到達表末了不能寫在while迴圈裡面了
	{
		p = p->next;
		j++;
		if (p == *L) break;
	}
	if (j < i - 1)
	{
		return ERROR;
	}
	s = (DuLinkList)malloc(sizeof(DulNode));
	s->data = e;
	q = p->next;
	p->next = s;
	q->prior = s;
	s->prior = p;
	s->next = q;

	return OK;
}

/* 初始條件:順序線性表L已存在 */
/* 操作結果:依次對L的每個資料元素輸出 */
Status ListTraverse(DuLinkList L)
{
	if (ListLength(L) < 1)
		return ERROR;
	DuLinkList p = L->next;
	while (p != L)
	{
		visit(p->data);
		p = p->next;
	}
	printf("\n");
	return OK;
}

/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L) */
/* 操作結果:刪除L的第i個數據元素,並用e返回其值,L的長度減1 */
Status ListDelete(DuLinkList *L, int i, ElemType *e)
{
	if (i >= 1 && i <= ListLength(*L))
	{
		DuLinkList p = (*L), q;
		int j = 0;
		while (j < i - 1) //找到第i-1個元素
		{
			p = p->next;
			++j;
		}

		q = p->next;
		*e = q->data;
		p->next = q->next;
		q->next->prior = p;
		free(q);
		return OK;
	}
	else return ERROR;
}


///*  隨機產生n個元素的值,建立帶表頭結點的單鏈線性表L(頭插法) */
void CreateListHead(DuLinkList *L, int n)
{
	DuLinkList p, q, s;
	int i = 0;
	srand(time(0));                         /* 初始化隨機數種子 */
	InitList(L);
	p = *L;

	for (i = 0; i != n; ++i)
	{
		s = (DuLinkList)malloc(sizeof(DulNode));
		s->data = i;
		q = p->next;
		p->next = s;
		q->prior = s;
		s->prior = p;
		s->next = q;
	}
}


/*  隨機產生n個元素的值,建立帶表頭結點的單鏈線性表L(尾插法) */
void CreateListTail(DuLinkList *L, int n)
{
	DuLinkList p, q;
	int i = 0;
	srand(time(0));                         /* 初始化隨機數種子 */
	InitList(L);
	p = *L;
	while (i < n)
	{
		i++;
		ListInsert(L, i, i);
	}
}

int main()
{
	DuLinkList L;
	ElemType e;
	Status i;
	int j, k;
	i = InitList(&L);
	printf("初始化L後:ListLength(L)=%d\n", ListLength(L));
	for (j = 1; j <= 5; j++)
		i = ListInsert(&L, 1, j);
	printf("在L的表頭依次插入1~5後:L.data=");
	ListTraverse(L);

	printf("ListLength(L)=%d \n", ListLength(L));
	i = ListEmpty(L);
	printf("L是否空:i=%d(1:是 0:否)\n", i);

	i = ClearList(&L);
	printf("清空L後:ListLength(L)=%d\n", ListLength(L));
	i = ListEmpty(L);
	printf("L是否空:i=%d(1:是 0:否)\n", i);

	for (j = 1; j <= 10; j++)
		ListInsert(&L, j, j);
	printf("在L的表尾依次插入1~10後:L.data=");
	ListTraverse(L);

	printf("ListLength(L)=%d \n", ListLength(L));

	ListInsert(&L, 1, 0);
	printf("在L的表頭插入0後:L.data=");
	ListTraverse(L);
	printf("ListLength(L)=%d \n", ListLength(L));

	GetElem(L, 5, &e);
	printf("第5個元素的值為:%d\n", e);

	for (j = 3; j <= 4; j++)
	{
		k = LocateElem(L, j);
		if (k)
			printf("第%d個元素的值為%d\n", k, j);
		else
			printf("沒有值為%d的元素\n", j);
	}


	k = ListLength(L); /* k為表長 */
	for (j = k + 1; j >= k; j--)
	{
		i = ListDelete(&L, j, &e); /* 刪除第j個數據 */
		if (i == ERROR)
			printf("刪除第%d個數據失敗\n", j);
		else
			printf("刪除第%d個的元素值為:%d\n", j, e);
	}
	printf("依次輸出L的元素:");
	ListTraverse(L);

	j = 5;
	ListDelete(&L, j, &e); /* 刪除第5個數據 */
	printf("刪除第%d個的元素值為:%d\n", j, e);

	printf("依次輸出L的元素:");
	ListTraverse(L);

	i = ClearList(&L);
	printf("\n清空L後:ListLength(L)=%d\n", ListLength(L));
	CreateListHead(&L, 20);
	printf("整體建立L的元素(頭插法):");
	ListTraverse(L);

	i = ClearList(&L);
	printf("\n刪除L後:ListLength(L)=%d\n", ListLength(L));
	CreateListTail(&L, 20);
	printf("整體建立L的元素(尾插法):");
	ListTraverse(L);

	system("pause");
	return 0;
}