1. 程式人生 > >C語言資料結構----雙向連結串列

C語言資料結構----雙向連結串列

概括:主要說明雙向連結串列的基本概念和具體操作以及原始碼。

一、基本概念

1.有了單鏈表以後我們可以把記憶體中小塊的空間聯絡在一起,並且把每一個小塊都儲存上我們想要儲存的數值。但是單鏈表只有一個next,我們每一次都要從頭開始遍歷整個連結串列,這樣的話如果我們對單鏈表進行逆序訪問那麼將是一項很耗時的操作。

2.雙向連結串列解決了上面的問題,我們不單對每一個數據節點都設定一個next,同時還有一個pre指標,這樣我們可以完成對連結串列的雙向查詢。

3.雙向連結串列的結構示意圖如下所示:

二、把單鏈表更改成為雙向連結串列

 1.首先更改連結串列中的header,連結串列中的header對應的是一個結構體,如下所示:

struct _tag_DLinkListNode
{
    DLinkListNode* next;
    DLinkListNode* pre;
};

在這裡相對於單鏈表增加了一個pre指標,作前驅。

2.在create函式中初始化將header.pre以及clear函式中的header.next都設定為NULL。

ret->header.pre = NULL;


3.其他地方的操作還要注意在插入一個節點和刪除一個節點函式中的改變。

三、雙向連結串列的具體操作

1.雙向連結串列的建立

DLinkList* DLinkList_Create()
{
	TDLinkList* ret = (TDLinkList*)malloc(sizeof (TDLinkList));
	if (ret != NULL)
	{
		ret->length = 0;
		ret->slider = NULL;
		ret->header.next = NULL;
		ret->header.pre = NULL;
	}
	
	return ret;
}

這裡的TDLinkList* ret = (TDLinkList*)malloc(sizeof (TDLinkList));是為連結串列頭獲取空間,連結串列中其他資料節點的空間是在主函式中定義的,也就是插入連結串列時候由 結構體進行定義。

2.雙向連結串列的清除、銷燬、以及獲取長度

這一部分要注意返回值的定義和返回值的型別。

3.雙向連結串列的插入操作

 在連結串列插入函式中,一共有四點需要注意。

(1)普通的插入方式,不是頭插法也不是尾插法,只是單純的把一個數據節點插入到連結串列中。基本操作示意圖如下:

這樣我們基本上使用四步操作就可以解決:

current->next = node;
node->pre = current;
next->pre = node;
node->pre = current;

(2)如果插入的節點是採用頭插法,而且連結串列中已經存在其他元素,那麼我們要進行判定,因為這個時候不可以再單純的令current = node->pre,這個時候的node是第一個元素,所以它的pre應該指向NULL。

 

程式碼實現:

if (current == (DLinkListNode*)slist)
		{
			node->pre = NULL;
		}

(3)當我們插入的節點是連結串列中的第0個位置,並且連結串列中沒有其他元素,也就是連結串列的長度為0的時候,這個時候我們插入的元素的node->pre指向的current是頭結點,顯然不應該這樣,也應該令node->pre = NULL,雖然老唐的判定是slist->length = 0但是我自己的判定current == (DLinkListNode*)slist已經包含了老唐的情況。



 這種情況的程式碼實現:

if (current == (DLinkListNode*)slist)
		{
			node->pre = NULL;
		}

(4)插入節點的第三種特殊情況:當我們從連結串列的尾部插入元素,這個時候current是倒數第一個節點,next是NULL,我們要插入的節點node在插入完成以後,node->next應該指向空。

這種情況下的程式碼實現:

if (next != NULL)
		{
		//	node->next = next;
			next->pre = node;			
		} 
		

(5)對然第二種情況已經實現了slist->length == 0的情況,但是假如我們的slist->length == 0的時候,我們的遊標並沒有指向當前插入的元素,為了解決這個問題,程式碼實現如下:

if (slist->length == 0)
		{
			slist->slider = node;
		} 
	

插入函式的整體實現如下所示:

int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
{
	TDLinkList *slist = (TDLinkList*)list;
	int ret = (slist != NULL);
	ret = ret && (pos >= 0);
	ret = ret && (node != NULL);
	int i = 0;
	if (ret)
	{
		DLinkListNode*current = (DLinkListNode*)slist;
		DLinkListNode*next = NULL;
		for (i = 0; (i < pos) && (current->next != NULL); i++)
		{
			current = current->next;
		}
		next = current->next;
		
		current->next = node;
		
		node->next = next;
		if (next != NULL)
		{
		//	node->next = next;
			next->pre = node;			
		} 
		
		node->pre = current;
		if (current == (DLinkListNode*)slist)
		{
			node->pre = NULL;
		}
		
		if (slist->length == 0)
		{
			slist->slider = node;
		} 
	
		slist->length++;
	}
	return ret;
}

4.雙向連結串列的刪除元素操作

刪除操作除了常規的操作以外也存在一些特殊的情況。

(1)常規的刪除連結串列中的一個元素,也就是在這個雙向連結串列中的不是第一個元素,也不是最後元素,而且這個時候的雙向連結串列已經有了一定的長度。如下圖所示:



具體的程式碼實現如下:

current->next = next;
next->node = current;

(2)刪除連結串列中的元素的第二種情況,我們要刪除連結串列中的第0個元素,這個時候我們頭結點的next被賦值為next(第1個節點),但是這個時候第一個節點應該變為第0個節點,而第0個節點指向的為header,所以這個時候next->pre = NULL。


程式碼實現:

current->next = next;
next->pre= NULL;

同時這種情況下要對next節點是否是為NULL 進行判定。

(3)刪除了第0個元素以後,連結串列中不再有其他元素,也就是我們刪除的元素是連結串列中的唯一節點,這個時候我們只需要將current->next = next,而並不需要進行next->pre =current,因為這個時候根本就不存在next->pre的情況了。

這裡不再需要next->pre = current,具體的程式碼實現如下:

if (next != NULL)

我們這種情況下next = = NULL,所以我們不再指向if下面的程式碼。

(4)如果刪除的連結串列中的最後一個節點,如果這個節點為空,那麼只執行current->next = next,這個判定if (next != NULL)已經完成,不再執行有關next->pre的操作。

具體程式碼實現如下:

if (next != NULL)

刪除函式的具體實現如下:

(5)如果我們要刪除的節點恰好是遊標現在所指向的元素,那麼我們需要將遊標指向next。

具體程式碼實現如下:

if (slist->slider == ret)
     {
	slist->slider = next;
     } 

刪除函式的具體實現程式碼如下:

DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode * ret = NULL;
	int i = 0;
	
	if ((slist != NULL) && (pos >=0) && (pos < slist->length))	
	{
		DLinkListNode* current = (DLinkListNode*)(slist);
		DLinkListNode*next = NULL;
		for (i = 0; i < pos; i++)
		{
			current = current->next;
		}
		ret = current->next;
		
		next->pre = current;*/ 
		next = ret->next;
		current->next = next;
		
		if (next != NULL)
		{
			next->pre = current;
			if (current == (DLinkListNode*)slist)
			{
				current->next = NULL;
				next->pre = NULL;
			}
			
		}
		
		 
		if (slist->slider == ret)
		{
			slist->slider = next;
		} 
		
		slist->length--;
			
	}
	return ret;
}

四、測試程式以及遊標

1.測試程式

(1)我們的插入方式如下:

 DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));
 DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));
 DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));
 DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));
 DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));

我們採用的尾插法,就是每一次插入一個元素都是從連結串列的尾部插入。

(2)我們在操作遊標之前,不必要對遊標進行復位,如果不對遊標進行復位,那麼我們採用尾插法將會把元素的遊標擠到第一個位置,那麼我們就可以正常操作遊標了。

(3)如果我們採用頭插法插入元素,插入方式如下:

DLinkList_Insert(list, (DLinkListNode*)&v1, 0);
DLinkList_Insert(list, (DLinkListNode*)&v2, 0);
DLinkList_Insert(list, (DLinkListNode*)&v3, 0);
DLinkList_Insert(list, (DLinkListNode*)&v4, 0);
DLinkList_Insert(list, (DLinkListNode*)&v5, 0);

(4)在我們進行遊標操作之前,我們要對遊標進行復位,因為頭插法將會把遊標順序的擠到最後一個位置,這個時候如果我們朦朧的將遊標再向後移動一個將會導致程式的崩潰,但是這個時候向前移動並不會出錯。

五、原始碼

1.雙向連結串列實現.c檔案

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

/************************************************************************
*這個結構體裡定義的是連結串列頭的資訊,我們的連結串列操作和連結串列遍歷都離不開連結串列頭 
************************************************************************/
typedef struct student
{
	DLinkListNode header;
	DLinkListNode *slider; //遊標 
	int length;
}TDLinkList;

/***********************************************************************************************
*函式名: DLinkList_Create
*引數:void
*返回值:DLinkList*型別,是一個void*型別,然後再由接收函式進行強制型別轉換 
*功能:建立連結串列,並返回連結串列頭 
***********************************************************************************************/ 
DLinkList* DLinkList_Create()
{
	/*
		為連結串列頭獲得空間,連結串列中其他資料節點的空間是在主函式中定義的,也就是插入連結串列時候由
		結構體進行定義。 
	*/
	TDLinkList* ret = (TDLinkList*)malloc(sizeof (TDLinkList));
	if (ret != NULL)
	{
		ret->length = 0;
		ret->slider = NULL;
		ret->header.next = NULL;
		ret->header.pre = NULL;
	}
	
	return ret;
}
/***********************************************************************************************
*函式名: DLinkList_Destroy
*引數:DLinkList* list 傳進來的是連結串列頭 
*返回值:void 
*功能:銷燬連結串列頭 
***********************************************************************************************/ 
void DLinkList_Destroy(DLinkList* list)
{
	free(list);
}
/***********************************************************************************************
*函式名: DLinkList_Clear
*引數:DLinkList* list 傳進來的是連結串列頭 
*返回值:void 
*功能:清空連結串列,並把連結串列頭資訊清空 
***********************************************************************************************/ 
void DLinkList_Clear(DLinkList* list)
{
	TDLinkList *slist = (TDLinkList*)list;
	if (slist != NULL)
	{
		slist->length = 0;
		slist->header.next = NULL;
		slist->header.pre = NULL;
		slist->slider = NULL;
	}
}
/***********************************************************************************************
*函式名: DLinkList_Length
*引數:DLinkList* list 傳進來的是連結串列頭 
*返回值:int型別的整數 
*功能:獲得連結串列長度,並將連結串列的長度返回 
***********************************************************************************************/ 
int DLinkList_Length(DLinkList* list)
{
	/*首先給返回值賦初值,如果函式的返回值為-1,則證明連結串列並不存在*/ 
	int ret = -1;
	TDLinkList *slist = (TDLinkList*)list;
	if (slist != NULL)
	{
		ret = slist->length;
	}
	return ret;
}
/***********************************************************************************************
*函式名: DLinkList_Insert
*引數:DLinkList* list 傳進來的是連結串列頭  DLinkListNode* node 要插入的資料節點,其實是我們
*實際要插入的資料節點的指標 int pos 要插入連結串列中的位置(注意這個是從0開始算起的) 
*返回值:int型別的整數 
*功能:如果插入元素成功返回1,否則返回其他。 
***********************************************************************************************/ 
int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
{
	TDLinkList *slist = (TDLinkList*)list;
	int ret = (slist != NULL);
	ret = ret && (pos >= 0);
	ret = ret && (node != NULL);
	int i = 0;
	if (ret)
	{
		DLinkListNode*current = (DLinkListNode*)slist;
		DLinkListNode*next = NULL;
		for (i = 0; (i < pos) && (current->next != NULL); i++)
		{
			current = current->next;
		}
		next = current->next;
		
		current->next = node;
		
		node->next = next;
		if (next != NULL)
		{
		//	node->next = next;
			next->pre = node;			
		} 
		
		node->pre = current;
		if (current == (DLinkListNode*)slist)
		{
			node->pre = NULL;
		}
		
		if (slist->length == 0)
		{
			slist->slider = node;
		} 
	
		slist->length++;
	}
	return ret;
}

/***********************************************************************************************
*函式名: DLinkList_Get
*引數:DLinkList* list 傳進來的是連結串列頭  int pos 要插入連結串列中的位置(注意這個是從0開始算起的) 
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的連結串列指標和位置,可以獲得這個位置上的資料節點資訊。 
***********************************************************************************************/
DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode* ret = NULL;
	int i = 0;
	if ((slist != NULL)&& (pos >= 0) && (pos < slist->length))
	{
		DLinkListNode*current = (DLinkListNode*)slist;
		//DLinkListNode*next = NULL;
		for (i = 0; i < pos; i++)
		{
			current = current->next;	
		}
		/*current永遠都是我們要找的節點的前一個節點*/ 
		ret = current->next;
	}
	return ret;
}
/***********************************************************************************************
*函式名: DLinkList_Delete
*引數:DLinkList* list 傳進來的是連結串列頭  int pos 要插入連結串列中的位置(注意這個是從0開始算起的) 
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的連結串列指標和位置,可以獲取刪除指定位置上的元素,並對指定位置上的元素進行刪除。 
***********************************************************************************************/
DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode * ret = NULL;
	int i = 0;
	
	if ((slist != NULL) && (pos >=0) && (pos < slist->length))	
	{
		DLinkListNode* current = (DLinkListNode*)(slist);
		DLinkListNode*next = NULL;
		for (i = 0; i < pos; i++)
		{
			current = current->next;
		}
		ret = current->next;

		next->pre = current;*/ 
		next = ret->next;
		current->next = next;
		
		if (next != NULL)
		{
			next->pre = current;
			if (current == (DLinkListNode*)slist)
			{
				current->next = NULL;
				next->pre = NULL;
			}
			
		}
		
		if (slist->slider == ret)
		{
			slist->slider = next;
		} 
		
		slist->length--;
			
	}
	return ret;
}
/***********************************************************************************************
*函式名: DLinkList_DeleteNode
*引數:DLinkList* list 傳進來的是連結串列頭  int pos 要插入連結串列中的位置(注意這個是從0開始算起的) 
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的連結串列指標和位置,通過遊標指向我們要刪除的元素,然後呼叫DLinkList_Delete函式
進行刪除。 
***********************************************************************************************/
DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode * ret = NULL;
	int i = 0;
	if (slist != NULL)
	{
		DLinkListNode* current = (DLinkListNode*)(slist);
		for (i = 0; i < slist->length; i++)
		{
			if (current->next == node)
			{
				ret = current->next;
				break;
			}
			current = current->next;
		}
		
		if (current != NULL)
		{
			DLinkList_Delete (list, i);
		}
	}
	return ret;
}

/***********************************************************************************************
*函式名: DLinkList_Reset
*引數:DLinkList* list 傳進來的是連結串列頭   
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的連結串列指標將遊標重新指向頭結點所指向的下一個元素的位置,也就是所謂的遊標復位。 
進行刪除。 
***********************************************************************************************/
DLinkListNode* DLinkList_Reset(DLinkList* list)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode* ret = NULL;
	if (slist != NULL)
	{
		slist->slider = slist->header.next;
		ret = slist->slider; 
	} 
	return ret;
}
/***********************************************************************************************
*函式名: DLinkList_Current
*引數:DLinkList* list 傳進來的是連結串列頭   
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的指標,找到遊標當前指向的元素,並將這個當前元素返回。 
***********************************************************************************************/
DLinkListNode* DLinkList_Current(DLinkList* list)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode* ret = NULL;
	if (slist != NULL)
	{
		ret = slist->slider;
	} 
	return ret;
}

/***********************************************************************************************
*函式名: DLinkList_Next
*引數:DLinkList* list 傳進來的是連結串列頭   
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的指標,找到遊標指向前一個元素,並將這個前一個元素返回。 
***********************************************************************************************/
DLinkListNode* DLinkList_Next(DLinkList* list)
{
    TDLinkList* slist = (TDLinkList*)list;
    DLinkListNode* ret = NULL;
    
    if( (slist != NULL) && (slist->slider != NULL) )
    {
        ret = slist->slider;
        slist->slider = ret->next;
    }
    
    return ret;
}
/***********************************************************************************************
*函式名: DLinkList_Pre
*引數:DLinkList* list 傳進來的是連結串列頭   
*返回值:DLinkListNode*型別 也就是返回的是一個連結串列的節點結構體指標 
*功能:通過傳進來的指標,找到遊標指向前一個元素,並將這個前一個元素返回。 
***********************************************************************************************/
DLinkListNode* DLinkList_Pre(DLinkList* list)
{
	TDLinkList* slist = (TDLinkList*)list;
	DLinkListNode* ret = NULL;
	if (slist != NULL && slist->slider != NULL)
	{
		slist->slider = slist->slider->pre; 
		ret = slist->slider;
	} 
	return ret;
}

2.雙向連結串列的標頭檔案

#ifndef _1_H_
#define _1_H_

typedef void DLinkList;
typedef struct _tag_DLinkListNode DLinkListNode;
/*這個結構體是聊表頭的一個成員*/ 
struct _tag_DLinkListNode
{
    DLinkListNode* next;
    DLinkListNode* pre;
};

DLinkList* DLinkList_Create();

void DLinkList_Destroy(DLinkList* list);

void DLinkList_Clear(DLinkList* list);

int DLinkList_Length(DLinkList* list);

int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);

DLinkListNode* DLinkList_Get(DLinkList* list, int pos);

DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);

DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);

DLinkListNode* DLinkList_Reset(DLinkList* list);

DLinkListNode* DLinkList_Current(DLinkList* list);

DLinkListNode* DLinkList_Next(DLinkList* list);

DLinkListNode* DLinkList_Pre(DLinkList* list);

#endif

3.測試程式

#include <stdio.h>
#include <stdlib.h>
#include "1.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

struct Value
{
    DLinkListNode header;
    int v;
};

int main(int argc, char *argv[])
{
    int i = 0;
    DLinkList* list = DLinkList_Create();
    struct Value* pv = NULL;
    struct Value v1;
    struct Value v2;
    struct Value v3;
    struct Value v4;
    struct Value v5;
    
    v1.v = 1;
    v2.v = 2;
    v3.v = 3;
    v4.v = 4;
    v5.v = 5;
    
    DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));
    DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));
    DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));
    DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));
    DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));
    
    DLinkList_Insert(list, (DLinkListNode*)&v1, 0);
    DLinkList_Insert(list, (DLinkListNode*)&v2, 0);
    DLinkList_Insert(list, (DLinkListNode*)&v3, 0);
    DLinkList_Insert(list, (DLinkListNode*)&v4, 0);
    DLinkList_Insert(list, (DLinkListNode*)&v5, 0);
    
    for(i=0; i<DLinkList_Length(list); i++)
    {
        pv = (struct Value*)DLinkList_Get(list, i);
        
        printf("插入的元素為:%d\n", pv->v);
    }
    
    printf("\n");
    

    //DLinkList_Delete(list, 0);
    //DLinkList_Delete (list)*/
    for(i=0; i<DLinkList_Length(list); i++)
    {
        pv = (struct Value*)DLinkList_Next(list);
        printf("%d\n", pv->v);
    }
    
    printf("\n");
 
	DLinkList_Reset(list);
    DLinkList_Next(list);
    
    pv = (struct Value*)DLinkList_Current(list);
    
    printf("%d\n", pv->v);
    
    DLinkList_DeleteNode(list, (DLinkListNode*)pv);
    
    pv = (struct Value*)DLinkList_Current(list);
    
    printf("%d\n", pv->v);
    
    DLinkList_Pre(list);
    
    pv = (struct Value*)DLinkList_Current(list);
    
    printf("%d\n", pv->v);
    
    printf("Length: %d\n", DLinkList_Length(list));
    
    DLinkList_Destroy(list);
    
	return 0;
}

相關推薦

C語言資料結構----雙向連結串列

概括:主要說明雙向連結串列的基本概念和具體操作以及原始碼。 一、基本概念 1.有了單鏈表以後我們可以把記憶體中小塊的空間聯絡在一起,並且把每一個小塊都儲存上我們想要儲存的數值。但是單鏈表只有一個next,我們每一次都要從頭開始遍歷整個連結串列,這樣的話如果我們對單鏈表進行逆

C語言資料結構——雙迴圈連結串列的插入操作順序

雙向連結串列與單鏈表的插入操作的區別 雙向連結串列因為存在前驅指標和後繼指標所以需要修改的指標多於單鏈表,但指標改動的順序同樣重要 單鏈表的插入 eg:在節點p的後面插入指標s s->next=p->next;//首先要使要插入的指標指向p->next p->next=s

C語言資料結構連結串列

目錄 1.什麼是連結串列 連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結點可以在執行時動態生成。

C語言資料結構----迴圈連結串列

主要講解釋迴圈連結串列的一些定義和具體的操作。 一、基本定義: 1.單鏈表的侷限:不可以迴圈。2.迴圈連結串列的定義:將單鏈表中最後一個元素的next指向第一個元素。3.迴圈連結串列擁有單鏈表的所有操作。4.迴圈連結串列的插入和單鏈表插入的差別:單鏈表的插入是 n

java資料結構——雙向連結串列

連結串列是非常常見的一類線性結構的資料結構,每個節點包含有指標域和資料域,常見的包括單項列表、雙向列表、迴圈列表。這篇文章將詳細介紹雙向連結串列。 雙端連結串列不同於單向連結串列僅有一個指標域指向下一個節點,而是同時持有下一個和上一個指標域,分別指向下一個和上一個節點,如下: 本文

資料結構-雙向連結串列-插入排序練習題

/* 若線性表中各結點的查詢概率不等,則可用如下策略提高順序查詢的效率:若找到指定的結點,則將該結點的fre域的值加1, 使得經常被查詢的結點位於表的前端。設雙向連結串列的儲存結構有四個域:pre,data,next和fre,data域為字元型,fre域為整形。 設計滿足該功能的

資料結構-雙向連結串列

單鏈表的結點中只有一個指示直接後繼的指標域,由此,從某個結點出發只能順指標往後尋查其他結點。若要尋查結點的直接前驅,則需從表頭指標出發。為克服單鏈表這種單向性的缺點,可利用雙向連結串列。 在雙向連結串

資料結構--雙向連結串列

1.之前接觸到的連結串列都只有一個指標,指向直接後繼,整個連結串列只能單方向從表頭訪問到表尾,這種結構的連結串列統稱為 “單向連結串列”或“單鏈表”。如果演算法中需要頻繁地找某結點的前趨結點,單鏈表的解決方式是遍歷整個連結串列,增加演算法的時間複雜度,影響整體效率。為了快速便

C語言---經典之雙向連結串列的實現

int dlist_ins_next(Dlist *list, DListElement *element, const void *data){    DListElement *new_element;    if (element == NULL && list->size !=

python演算法與資料結構-雙向連結串列(40)

一、雙向連結串列的介紹   一種更復雜的連結串列是“雙向連結串列”或“雙面連結串列”。每個節點有兩個連結:一個指向前一個節點,當此節點為第一個節點時,指向空值;而另一個指向下一個節點,當此節點為最後一個節點時,指向空值。      上圖是雙向連結串列的結構

資料結構-雙向連結串列(Python實現)

資料結構在程式設計世界中一直是非常重要的一環,不管是開發還是演算法,哪怕是單純為了面試,資料結構都是必修課,今天我們介紹連結串列中的一種——雙向連結串列的程式碼實現。 好了,話不多說直接上程式碼。 雙向連結串列 首先,我們定義一個節點類:Node class Node: def __init__(se

資料結構連結串列C語言實現以及使用場景分析

連結串列是資料結構中比較基礎也是比較重要的型別之一,那麼有了陣列,為什麼我們還需要連結串列呢!或者說設計連結串列這種資料結構的初衷在哪裡? 這是因為,在我們使用陣列的時候,需要預先設定目標群體的個數,也即陣列容量的大小,然而實時情況下我們目標的個數我們是不確定的,因此我們總是要把陣列的容量設定的

資料結構連結串列(List)的C語言的實現

#include<stdio.h> #include<stdlib.h> #include<stdbool.h> typedef struct Node{ int data; struct Node * next; }NODE,*PNO

C語言資料結構——連結串列

轉自https://www.cnblogs.com/chenxiaohei/p/6862791.html /* 連結串列節點的插入與刪除 編譯環境:VC++ 6.0 編譯系統:windows XP SP3 */ #inc

C語言小知識 --- 資料結構 --- 單向連結串列 ...... 嗯 ......未完待續

一、     連結串列很簡單,普通的連結串列說白了就是我們之前學過了的結構體作為多個節點連結而成一條資料連出來的,奇怪了,結構體它們怎麼可以一個連著一個呢? 以單向連結串列為例子:     其實很簡單,之所以說它們連在一起,因為每個結構體(連結串列節點)裡面存放著一種指

c語言資料結構中兩個有序連結串列合併為一個新連結串列

先建立兩個連結串列La和Lb,並向La Lb中輸入值,然後再建立一個Lc,Lc指向La,具體程式碼如下: #include "stdafx.h" #include"stdio.h" #include"stdlib.h" #define OK 1 #define OVERFL

資料結構——有序連結串列合併(C語言版)

有序連結串列合併 兩個有序的連結串列,要求將其合併為一個連結串列,並且該連結串列保持有序!! 這裡所講的是連結串列升序! 這裡我們的實驗資料,以及思路如圖所示!! 實驗資料: 連結串列1:1, 3, 5, 7 連結串列2:1, 2, 4 ,5

C語言資料結構----連結串列(靜態連結串列

看了老唐的靜態連結串列,越發的覺得自己是菜鳥了,因為看的過程實在是太糾結了。下面就把自己看老唐靜態連結串列的內容寫下來。 一、靜態連結串列的基礎知識 1.單鏈表的缺陷:單鏈表的實現嚴重依賴指標,每一個數據元素都要有額外的指標域。 2.在靜態表中我們把資料元素放在一個數組裡,

C語言資料結構之靜態連結串列實現(A-B)U(B-A)

時間複雜度O(3n)不是很難,直接貼程式碼:StaticLinkList.h#ifndef _STATIC_LINK_LIST_H_ #define _STATIC_LINK_LIST_H_ #define MAXSIZE 100 typedef enum {ERROR,OK

資料結構C語言——用二叉連結串列示二叉樹

標頭檔案,定義棧和結構體的功能: /* 二叉樹的連結表示*/ #include <stdio.h> #include <stdlib.h> typedef char DataType; struct BinTreeNode; typedef