【C/C++】【資料結構】雙向連結串列操作
阿新 • • 發佈:2019-02-10
目錄
雙向連結串列操作
像雙向連結串列的求長,判空,遍歷,查詢,檢索,之類的操作都和單鏈表一樣的。不過我還是在了文中。
標頭檔案定義
#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;
}