理解雙向鏈表
和單鏈表類似,單鏈表是結點只包含了指向下一個結點的後繼指針域,而雙向鏈表的結點增加了一個指向前驅的指針域。這樣以來方便從某一結點開始,方便訪問前一個結點和後一個結點。
雙向鏈表的插入分析
一般插入:
添加輔助指針current和next。
current的後繼指針指向插入結點node,node結點的後繼指針指向next結點處
next結點的前驅指針指向node結點,node結點的前驅指針指向current結點處
插入頭部結點(0號元素):
需要異常處理,輔助指針current指向頭部結點,如果current的後繼指針指向Null,不作處理,如果current的後繼指針不爲Null,則輔助指針next爲current的後繼指針指向得結點,current的前驅指針指向Null。
插入尾部結點:
雙向鏈表的刪除分析
普通刪除:
刪除頭結點:
鏈表中有其他元素
刪除0號元素時,應該讓next的前驅指針指向Null
只有一個元素
刪除尾結點:
//DLinkList.h
#pragma once
typedef void DLinkList;
typedef struct tag_DLinkListNode
{
struct tag_DLinkListNode *next;
struct tag_DLinkListNode *prev;
}TDLinkListNode;
DLinkList* DLinkList_Creat();
void DLinkList_Destroy(DLinkList *list);
void DLinkList_Clear(DLinkList *list);
int DLinkList_GetLength(DLinkList *list);
int DLinkList_Inster(DLinkList *list, TDLinkListNode *node, int pos);
TDLinkListNode *DLinkList_Get(DLinkList *list, int pos);
TDLinkListNode *DLinkList_Delete(DLinkList *list, int pos);
TDLinkListNode *DLinkList_DeleteNode(DLinkList *list, TDLinkListNode *node);
TDLinkListNode *DLinkList_Reset(DLinkList *list);
TDLinkListNode *DLinkList_Current(DLinkList *list);
TDLinkListNode *DLinkList_Next(DLinkList *list);
TDLinkListNode *DLinkList_Prev(DLinkList *list);
//DLinkList .c
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "DLinkList.h"
typedef struct tag_DLinkList
{
TDLinkListNode header;
TDLinkListNode *slider;
int length;
}TDLinkList;
DLinkList *DLinkList_Creat()
{
TDLinkList *list = NULL;
list = (TDLinkList *)malloc(sizeof(TDLinkList));
memset(list, 0, sizeof(TDLinkList));
list->header.next = NULL;
list->header.prev = NULL;
list->slider = NULL;
list->length = 0;
return list;
}
void DLinkList_Destroy(DLinkList * list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Destroy err: list = NULL");
return;
}
temp = (TDLinkList *)list;
free(temp);
return;
}
void DLinkList_Clear(DLinkList *list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Clear err: list = NULL");
return;
}
temp = (TDLinkList *)list;
temp->length = 0;
temp->header.next = NULL;
temp->header.prev = NULL;
temp->slider = NULL;
return;
}
int DLinkList_GetLength(DLinkList *list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_GetLength err: list = NULL");
return -1;
}
temp = (TDLinkList *)list;
return temp->length;
}
int DLinkList_Inster(DLinkList *list, TDLinkListNode *node, int pos)
{
TDLinkList *temp = NULL;
if (list == NULL || node == NULL || pos < 0)
{
printf("DLinkList_Inster err: list = NULL || node = NULL || pos < 0");
return -1;
}
temp = (TDLinkList *)list;
if (pos > temp->length)
{
printf("DLinkList_Get err: pos > temp->length");
return -2;
}
TDLinkListNode *current = &(temp->header);
TDLinkListNode *next = NULL;
int i = 0;
for (i = 0; i < pos; i++)
{
current = current->next;
}
//遊標指向第一個插進來的節點
if (temp->slider == NULL)
{
temp->slider = node;
}
//插入0號元素時
if (current == &(temp->header))
{
//當插入節點的next = null(異常處理)
if (current->next != NULL)
{
next = current->next;
}
current->prev = NULL;
}
next = current->next;
current->next = node;
node->next = next;
//如果刪除尾結點時輔助指針next = null(異常處理)
if (next != NULL)
next->prev = node;
node->prev = current;
temp->length++;
return 0;
}
TDLinkListNode *DLinkList_Get(DLinkList *list, int pos)
{
TDLinkList *temp = NULL;
if (list == NULL || pos < 0)
{
printf("DLinkList_Get err: list = NULL");
return NULL;
}
temp = (TDLinkList *)list;
if (pos > temp->length)
{
printf("DLinkList_Get err: pos > temp->length");
return NULL;
}
TDLinkListNode *current = &(temp->header);
TDLinkListNode *ret = NULL;
int i = 0;
for (i = 0; i < pos; i++)
{
current = current->next;
}
ret = current->next;
return ret;
}
TDLinkListNode *DLinkList_Delete(DLinkList *list, int pos)
{
TDLinkList *temp = NULL;
if (list == NULL || pos < 0)
{
printf("DLinkList_Delete err: list = NULL || node = NULL || pos < 0");
return NULL;
}
temp = (TDLinkList *)list;
if (pos > temp->length)
{
printf("DLinkList_Delete err: pos > temp->length");
return NULL;
}
TDLinkListNode *current = &(temp->header);
TDLinkListNode *next = NULL;
TDLinkListNode *ret = NULL;
int i = 0;
for (i = 0; i < pos; i++)
{
current = current->next;
}
ret = current->next;
next = ret->next;
current->next = next;
if (next != NULL)
{
next->prev = current;
//刪除0號元素
if (current == &(temp->header))
{
next->prev = NULL;
}
}
//刪除的節點正好是遊標所指的節點,那麼遊標下一
if (temp->slider == ret)
temp->slider = next;
if (temp->length == 0)
{
temp->header.next = NULL;
temp->header.prev = NULL;
temp->slider = NULL;
}
temp->length--;
return ret;
}
TDLinkListNode * DLinkList_DeleteNode(DLinkList *list, TDLinkListNode *node)
{
if (list == NULL || node == NULL)
{
printf("LinkList_DeleteNode err: list = NULL || node = NULL");
return NULL;
}
int i = 0;
TDLinkList *temp = (TDLinkList *)list;
TDLinkListNode *current = &temp->header;
TDLinkListNode *ret = NULL;
for (i = 0; i < temp->length; i++)
{
if (current->next == node)
{
ret = current->next;
break;
}
current = current->next;
}
if (ret != NULL)
{
DLinkList_Delete(temp, i);
}
return ret;
}
TDLinkListNode * DLinkList_Reset(DLinkList * list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Reset err: list = NULL");
return NULL;
}
temp = (TDLinkList *)list;
temp->slider = DLinkList_Get(temp, 0);
return temp->slider;
}
TDLinkListNode * DLinkList_Current(DLinkList * list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Current err: list = NULL");
return NULL;
}
temp = (TDLinkList *)list;
return temp->slider;
}
TDLinkListNode * DLinkList_Next(DLinkList * list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Next err: list = NULL");
return NULL;
}
temp = (TDLinkList *)list;
temp->slider = temp->slider->next;
return temp->slider;
}
TDLinkListNode * DLinkList_Prev(DLinkList * list)
{
TDLinkList *temp = NULL;
if (list == NULL)
{
printf("DLinkList_Prev err: list = NULL");
return NULL;
}
temp = (TDLinkList *)list;
temp->slider = temp->slider->prev;
return temp->slider;
}
//測試代碼
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "DLinkList.h"
typedef struct tag_Value
{
TDLinkListNode node;
int val;
}TValue;
int main(int argc, char** argv)
{
DLinkList *list = (DLinkList *)DLinkList_Creat();
if (list == NULL)
{
printf("DLinkList_Creat err: list = NULL");
return -1;
}
TValue v1, v2, v3, v4, v5;
v1.val = 1;
v2.val = 2;
v3.val = 3;
v4.val = 4;
v5.val = 5;
DLinkList_Inster(list, (TDLinkListNode*)&v1, DLinkList_GetLength(list));
DLinkList_Inster(list, (TDLinkListNode*)&v2, DLinkList_GetLength(list));
DLinkList_Inster(list, (TDLinkListNode*)&v3, DLinkList_GetLength(list));
DLinkList_Inster(list, (TDLinkListNode*)&v4, DLinkList_GetLength(list));
DLinkList_Inster(list, (TDLinkListNode*)&v5, DLinkList_GetLength(list));
int i = 0;
for (i = 0; i < DLinkList_GetLength(list); i++)
{
TValue *v = (TValue *)DLinkList_Get(list, i);
printf("val = %d\n", v->val);
}
printf("\n");
DLinkList_Delete(list, 0);
DLinkList_DeleteNode(list, DLinkList_Get(list, DLinkList_GetLength(list) - 1));
printf("%d\n", DLinkList_GetLength(list));
for (i = 0; i < DLinkList_GetLength(list); i++)
{
TValue *v = (TValue *)DLinkList_Get(list, i);
printf("val = %d\n", v->val);
}
printf("\n");
DLinkList_Delete(list, 1);
DLinkList_Reset(list);
DLinkList_Next(list);
TValue *v_1 = (TValue *)DLinkList_Current(list);
printf("val = %d\n", v_1->val);
TValue *v_2 = (TValue *)DLinkList_Prev(list);
printf("val = %d\n", v_2->val);
system("pause");
return 0;
}