1. 程式人生 > >【C/C++】【資料結構】雙向連結串列操作

【C/C++】【資料結構】雙向連結串列操作

目錄

標頭檔案定義

測試檔案

雙向連結串列操作

像雙向連結串列的求長,判空,遍歷,查詢,檢索,之類的操作都和單鏈表一樣的。不過我還是在了文中。

標頭檔案定義

#ifndef _DOUBLELINKLIST_H_
#define _DOUBLELINKLIST_H_

#include <stdlib.h>
#include <stdio.h>

#define SUCCESS    10000
#define FAILURE    10001
#define TRUE       10002
#define FALSE      10003

typedef int ElemType;

struct node
{
	ElemType data;
	struct node *next;
	struct node *prior;
};

typedef struct node Node;

int LinkInit( Node **ppHeadNode);
int LinkInsert( Node *pHeadNode, int position, ElemType e);
int LinkLength( Node *pHeadNode);
int LinkEmpty( Node *pHeadNode);
int LinkTraverse( Node *pHeadNode, void (*visit)(ElemType));
int GetElem( Node *pHeadNode, int position, ElemType *e);
int LocateElem( Node *pHeadNode, ElemType e, int compare(ElemType, ElemType));
int LinkDelete( Node *pHeadNode, int position, ElemType *e);
int LinkClear( Node *pHeadNode);
int LinkDestory( Node **ppHeadNode);
int ReverseLink( Node *pHeadNode);

#endif

雙向連結串列的初始化

//連結串列初始化
int LinkInit(Node **ppHeadNode)
{
	if( NULL == ppHeadNode)//入參判斷
	{
		return FAILURE;
	}

	(*ppHeadNode) = (Node *) malloc (sizeof(Node));//為(*ppHeadNode)分配節點空間

	if( NULL == (*ppHeadNode))
	{
		return FAILURE;
	}

	(*ppHeadNode)->next = NULL;
	(*ppHeadNode)->prior = NULL;

	return SUCCESS;
}

雙向連結串列的插入 

雙鏈表的插入操作的基本思路是這樣的。

1.定位。確定插入的位置。程式碼中的count就是用來定位的,pNode則是儲存定位的到的節點

2.分配空間。定義一個新節點pNewNode 並給他分配空間。

3.傳值。把要插入的資料傳給剛剛已分配好空間的新節點。

4.執行插入操作。插入操作見下圖。

//雙向連結串列插入操作,position 是要插入的位置, e 是要插入的資料
int LinkInsert(Node *pHeadNode, int position, ElemType e)
{
	if( NULL == pHeadNode || position < 1)//入參判斷,連結串列要存在, position 最小為1
	{
		return FAILURE;
	}

	if( position > LinkLength(pHeadNode) + 1)//入參判斷,確保 position 有效
	{
		return FAILURE;
	}

	Node *pNewNode = NULL;		//pNewNode 為要插入的新節點
	Node *pNode = pHeadNode;	//pNode 遍歷連結串列,最終指向要插入位置的前一個節點
	int count = 0;			//count 用來確定 pNode 指向的位置

	while( count < position - 1)
	{
		pNode = pNode->next;
		count++;
	}

	if( count != position - 1)	//再次確認位置
	{
		return FAILURE;
	}

	pNewNode = (Node *) malloc (sizeof(Node));//為 pNewNode 分配節點空間
	pNewNode->data = e;				//把要插入的資料傳給新節點
	
	//插入操作
	pNewNode->prior = pNode;		//先讓pNewNode附著在pNode之後,使pNewNode連結上鍊表
	pNewNode->next = pNode->next;	

	pNode->next = pNewNode;		//再斷開多餘的連結
	if( pNode->next != NULL)	//如果pNode不是尾節點
	{
		pNode->next->prior = pNewNode;
	}

	return SUCCESS;
}

雙線連結串列求連結串列長度

//求連結串列長度
int LinkLength(Node *pHeadNode)
{
	if( NULL == pHeadNode)		//入參判斷
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode;	//pNode 遍歷連結串列
	int length = 0;			//length 記錄連結串列長度

	while( pNode->next != NULL)
	{
		pNode = pNode->next;
		length++;
	}

	return length;
}

雙向連結串列的判空

//判斷連結串列是否為空
int LinkEmpty(Node *pHeadNode)
{
	return pHeadNode->next == NULL ? TRUE : FALSE;
}

雙向連結串列的遍歷 

//連結串列的遍歷操作
int LinkTraverse(Node *pHeadNode, void (*visit)(ElemType))
{
	if( NULL == pHeadNode)		//入參判斷
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode;	//pNode 遍歷連結串列

	while( pNode->next != NULL)
	{
		pNode = pNode->next;
		(*visit)(pNode->data);
	}

	return SUCCESS;
}

雙向連結串列的查詢(通過位置求值)

//獲取某個位置上的資料
int GetElem(Node *pHeadNode, int position, ElemType *e)
{
	if( NULL == pHeadNode || position < 1)	//入參判斷
	{
		return FAILURE;
	}

	if( position > LinkLength(pHeadNode) )
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode;	//pNode 遍歷連結串列
	int count;

	while( count < position)	//讓pNode指向position位置的節點
	{
		pNode = pNode->next;
		count++;
	}

	if( count != position)		//再次確認位置
	{
		return FAILURE;
	}

	*e = pNode->data;		//傳值

	return SUCCESS;
}

雙向連結串列的檢索(通過值求位置)

//函式返回連結串列中第一個與元素e滿足關係compare()的位置
int LocateElem(Node *pHeadNode, ElemType e, int compare(ElemType, ElemType))
{
	if( NULL == pHeadNode)		//入參判斷
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode->next;	//pNode 遍歷連結串列
	int count = 0;				//count 記錄位置

	while( pNode != NULL)
	{
		if( TRUE == compare(pNode->data, e))	//如果pNode->data與e滿足關係compare
		{
			return count + 1;	//返回位置
		}
		pNode = pNode->next;
		count++;
	}

	return FAILURE;
}

雙向連結串列的刪除 

//連結串列的刪除操作,position 為要刪除的位置,*e 儲存被刪除的資料
int LinkDelete(Node *pHeadNode, int position, ElemType *e)
{
	if( NULL == pHeadNode || position < 1)		//入參判斷
	{
		return FAILURE;
	}

	if( position > LinkLength(pHeadNode))
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode;	//pNode 遍歷連結串列,最終指向要刪除的前節點
	int count = 0;			//count 確保位置

	while( count < position )
	{
		pNode = pNode->next;
		count++;
	}

	if( count != position )	//再次確認位置
	{
		return FAILURE;
	}

	//刪除操作
	*e = pNode->data;	//記錄將被刪除節點上的資料

	pNode->prior->next = pNode->next;	//剝離要刪除的節點
	pNode->next->prior = pNode->prior;

	free(pNode);		//釋放已經被剝離的節點的空間
	pNode = NULL;

	return SUCCESS;
}

雙向連結串列的重置

//清空連結串列
int LinkClear(Node *pHeadNode)
{
	if( NULL == pHeadNode)		//入參判斷
	{
		return FAILURE;
	}

	Node *pNode = pHeadNode->next;	//pNode 指向被清空的節點

	while( NULL != pNode->next)		//迴圈銷燬節點
	{
		pHeadNode->next = pNode->next;	//剝離pNode
		pNode->next->prior = pHeadNode;
		
		free(pNode);
		pNode = pNode->next;
	}
	
	if( NULL != pNode)		//清空最後一個節點
	{
		free(pNode);
		pNode = NULL;
		pHeadNode->next = NULL; //頭結點初始化
	}
	return SUCCESS;
}

雙向連結串列的銷燬

//銷燬連結串列
int LinkDestory(Node **ppHeadNode)
{
	if( NULL == ppHeadNode )	//入參判斷
	{
		return FAILURE;
	}

	Node *pNode = NULL;			//pNode 指向將被銷燬的節點的下一個節點

	while( NULL != (*ppHeadNode) )
	{
		pNode = (*ppHeadNode)->next;	//將下個要被銷燬的節點的地址傳給pNode
		free(*ppHeadNode);					//銷燬 *ppHeadNode
		(*ppHeadNode) = pNode;			//把pNode裡的地址傳給*ppHeadNode
	}

	if( NULL == (*ppHeadNode))		//確認節點都被銷燬
	{
		return SUCCESS;
	}

	return FAILURE;
}

測試檔案

#include <stdio.h>
#include "doublelinklist.h"
#include <time.h>

void print(ElemType e)
{
	printf("%d ", e);
}

int eq(ElemType L_e, ElemType e)
{
	return L_e == e ? TRUE : FALSE;
}

int gt(ElemType L_e, ElemType e)
{
	return L_e > e ? TRUE : FALSE;
}

int lt(ElemType L_e, ElemType e)
{
	return L_e < e ? TRUE : FALSE;
}

int main()
{
	Node *pHeadNode;
	int ret, position, i;
	ElemType e;

	srand(time(NULL));

	ret = LinkInit(&pHeadNode);			//連結串列初始化
	if( FAILURE == ret)
	{
		printf("Init failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("Init success.\n");
	}

	for( i = 0; i < 10; i++)
	{
		e = rand() % 20;
		ret = LinkInsert(pHeadNode, i+1, e);		//連結串列插入
		if( FAILURE == ret)
		{
			printf("Insert failure.\n");
		}
		else if( SUCCESS == ret)
		{
			printf("Insert success.\n");
		}
	}

	ret = LinkLength(pHeadNode);					//連結串列求長
	if( FAILURE == ret)
	{
		printf("Length failure.\n");
	}
	else
	{
		printf("Length = %d\n", ret);
	}


	ret = LinkEmpty(pHeadNode);					//連結串列判空
	if( FALSE == ret)
	{
		printf("Not Empty.\n");
	}
	else if( TRUE == ret)
	{
		printf("Empty.\n");
	}

	ret = LinkTraverse(pHeadNode, print);		//連結串列遍歷
	if( FAILURE == ret)
	{
		printf("\nTraverse failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("\nTraverse success.\n");
	}

	position = 4;
	ret = GetElem(pHeadNode, position, &e);		//獲取某位置上的資料
	if( FAILURE == ret)
	{
		printf("Get %dth element failure.\n", position);
	}
	else if( SUCCESS == ret)
	{
		printf("%dth element is %d.\n", position, e);
	}

	e = 10;
	ret = LocateElem(pHeadNode, e, eq);			//返回10在連結串列第一次出現的位置
	if( FAILURE == ret)
	{
		printf("Locate element %d failure.\n", e);
	}
	else
	{
		printf("%d is %dth element.\n", e, ret);
	}

	position = 3;
	ret = LinkDelete(pHeadNode, position, &e);	//連結串列刪除
	if( FAILURE == ret)
	{
		printf("Delete failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("Delete %dth element %d success.\n", position, e);
	}

	ret = LinkTraverse(pHeadNode, print);		//連結串列遍歷
	if( FAILURE == ret)
	{
		printf("\nTraverse failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("\nTraverse success.\n");
	}

	ret = LinkClear(pHeadNode);			//連結串列重置
	if( FAILURE == ret)
	{
		printf("Clear failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("Clear success.\n");
	}
	
	ret = LinkLength(pHeadNode);					//連結串列求長
	if( FAILURE == ret)
	{
		printf("Length failure.\n");
	}
	else
	{
		printf("Length = %d\n", ret);
	}

	ret = LinkDestory(&pHeadNode);		//連結串列銷燬
	if( FAILURE == ret)
	{
		printf("Destory failure.\n");
	}
	else if( SUCCESS == ret)
	{
		printf("Destory success.\n");
	}
	for( i = 0; i < 4; i++)
	{
		e = rand() % 20;
		ret = LinkInsert(pHeadNode, i+1, e);		//連結串列插入
		if( FAILURE == ret)
		{
			printf("Insert failure.\n");
		}
		else if( SUCCESS == ret)
		{
			printf("Insert success.\n");
		}
	}
	return 0;
}