1. 程式人生 > >面試題之雙向連結串列簡單詳述

面試題之雙向連結串列簡單詳述

        雙向連結串列其實是單鏈表的改進,對單鏈表進行操作時,有時要對某個節點的直接前驅進行操作,又必須從表頭開始查詢。由於單鏈表每個節點只有一個直接後繼節點儲存地址的練域,因此運用單鏈表無法辦到,這樣就引出了一個既有儲存直接後繼節點地址的練域,又有儲存直接前驅節點地址的練域的上向連結串列節點結構。

(1)建立一個雙向連結串列

雙向連結串列的定義如下:

typedef struct DbNode
{
	int data;       //節點資料
	DbNode *left;   //前驅節點指標
	DbNode *right;  //後繼節點指標
}DbNode;
建立雙向連結串列(為了方便,這裡定義了3個函式)如下所示:

CreateNode()根據資料建立一個節點,返回新建立的節點。

CreateList()函式根據一個節點資料建立連結串列的表頭,返回表頭節點。

AppendNode()函式總在表尾插入新節點(其內部條用CreateNode()生成節點),返回表頭節點。

//根據資料建立節點
DbNode *CreateNode(int data)
{
	DbNode *pNode = (DbNode *)malloc(sizeof(DbNode));
	pNode->data = data;
	pNode->left = NULL;	//建立新節點時,
	pNode->right = NULL;	//讓前驅和後繼指標都為NULL
	
	return pNode;
}
//建立連結串列
DbNode *CreateList(int head)		//引數給出表頭節點資料
{									//表頭節點不作為存放有意義資料的節點
	DbNode *pNode = (DbNode *)malloc(sizeof(DbNode));
	pNode->data = head;
	pNode->left = NULL;
	pNode->right = NULL;

	return pNode;
}
//總是在表尾插入新節點,返回表頭節點
DbNode *AppendNode(DbNode *head, int data)
{
	DbNode *node = CreateNode(data);
	DbNode *p = head;
	DbNode *q = NULL;

	while(NULL != p)
	{
		q = p;
		p = p->right;
	}
	q->right = node;
	node->left = q;

	return head;
}

        可以使用其中的CreateList和AppendNode來生成一個連結串列,下面是一個生成從節點0---9的雙向連結串列。

	DbNode *head = CreateList(0);

	for(int i=1; i<10; i++)
	{
		head = AppendNode(head, i);
	}

上向連結串列的測長:
//雙向連結串列的測長
int GetLength(DbNode *head)
{
	int count = 1;
	DbNode *pnode = NULL;

	if(NULL == head)
	{
		return 0;
	}
	pnode = head->right;
	while(NULL != pnode)
	{
		pnode = pnode->right;
		count++;
	}

	return count;
}

雙向連結串列的列印:
//雙向連結串列的列印 
void PrintList(DbNode *head)
{
	DbNode *pnode = NULL;
	if(NULL == head)
	{
		return;
	}
	pnode = head;
	while(NULL != pnode)
	{
		printf("%d ", pnode->data);
		pnode = pnode->right;
	}
	printf("\n");
}

雙向連結串列的節點查詢:
//雙向連結串列的節點查詢
DbNode *FindNode(DbNode *head, int data)
{								//data為將要查詢的節點的資料
	DbNode *pnode = head;

	if(NULL == head)
	{
		return NULL;
	}
	//找到資料或者到達連結串列末尾退出
	while(NULL != pnode->right && pnode->data != data)
	{
		pnode = pnode->right;
	}
	if(NULL == pnode)  //沒有找到
	{
		return NULL;
	}
	return pnode;
}

雙向連結串列的節點插入:
//雙向連結串列的節點插入
void InsertNode(DbNode *node, int data)
{
	DbNode *newnode = CreateNode(data);
	//DbNode *p = NULL;

	if(NULL == node)
	{
		return ;
	}
	if(NULL == node->right)		//node為最後一個節點
	{	
		node->right = newnode;
		newnode->left = node;
	}
	else
	{						//node為中間節點
		newnode->right = node->right; //newnode向右連線
		node->right->left = newnode;	
		node->right =  newnode;			//newnode向左連線
		newnode->left = node;
	}
}

雙向連結串列的節點刪除:
//雙向連結串列的節點刪除
//刪除滿足指定條件的節點,返回表頭節點,節點不存在刪除失敗返回NULL
DbNode *DeleteNode(DbNode *head, int data)
{
	DbNode *ptmp = head->right;
	DbNode *pnode = FindNode(head, data);
	if(NULL == pnode)
	{
		return NULL;
	}
	else if(NULL == pnode->left)	//刪除第一個節點
	{
		head = pnode->right;		//head指向第二個節點
		//head = ptmp;
		if(NULL != head)
		{
			head->left = NULL;
		}
	}
	else if(NULL == pnode->right)	//刪除最後一個節點
	{
		pnode->left->right = NULL;
		//pnode->left = pnode->right = NULL;
	}
	else				//刪除中間節點
	{
		pnode->left->right = pnode->right;
		pnode->right->left = pnode->left;
	}

	free(pnode);
	return head;
}

下面是測試的主函式:
int main()
{
	DbNode *head = CreateList(0);

	for(int i=1; i<10; i++)
	{
		head = AppendNode(head, i);		//建立
	}
	int count = GetLength(head);		//測長
	printf("length = %d\n", count);	

	printf("print list...");			//列印
	PrintList(head);

	DbNode *FNode = FindNode(head, 7);	//查詢
	printf("find node data = %d\n", FNode->data);

	printf("insert node data 888....\n");	
	InsertNode(FNode, 888);				//插入
	PrintList(head);

	printf("Delete node....\n");
	head = DeleteNode(head, 0);			//刪除
	PrintList(head);

	return 0;
}

下面是執行結果:
length = 10
print list...0 1 2 3 4 5 6 7 8 9
find node data = 7
insert node data 888....
0 1 2 3 4 5 6 7 888 8 9
Delete node....
1 2 3 4 5 6 7 888 8 9
Press any key to continue




相關推薦

試題雙向連結串列簡單詳述

        雙向連結串列其實是單鏈表的改進,對單鏈表進行操作時,有時要對某個節點的直接前驅進行操作,又必須從表頭開始查詢。由於單鏈表每個節點只有一個直接後繼節點儲存地址的練域,因此運用單鏈表無法辦到,這樣就引出了一個既有儲存直接後繼節點地址的練域,又有儲存直接前驅節點地

雙向連結串列簡單實現--資料結構與演算法紀錄片第一記

  從這個月開始得準備春招的東西,所以打算重新學習資料結構與演算法,以後的部落格就以這個為主。   今天是線性結構中的雙向連結串列。   程式碼實現與測試:   DoubleLinkNode:  package linear.doublelink;/** * @Description: 連結串列節點結

資料結構-----------線性表(下篇)雙向連結串列

//----------雙向連結串列的儲存結構------------ typedef struct DuLNode { ElemType date; struct DoLNode *prior; struct DoLNode *next; } DoLNode,*DoLinkList;

試題】求連結串列的環入口點

環入口點:我們設A是連結串列的起點,B是環的入口點,C是環內快慢指標的相遇點。兩個快慢指標定義為slow和fast. slow走的路程:A->B->C; fast走的路程:A->B->C->B->C; 2*(x+y)=x+y+z+y 

資料結構與演算法(五)-線性表雙向連結串列雙向迴圈連結串列

前言:前面介紹了迴圈連結串列,雖然迴圈連結串列可以解決單鏈表每次遍歷只能從頭結點開始,但是對於查詢某一節點的上一節點,還是頗為複雜繁瑣,所以可以在結點中加入前一個節點的引用,即雙向連結串列 一、簡介   雙向連結串列:在連結串列中,每一個節點都有對上一個節點和下一個節點的引用或指標,即從一個節點出發可以有

劍指Offer.試題18.刪除連結串列中重複的節點

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5 思路: 設定三個指標。

Java手寫LinkedList 應用資料結構雙向連結串列

作為Java程式設計師,紮實的資料結構演算法能力是必須的 LinkedList理解的最好方式是,自己手動實現它         ArrayList和LinkedList是順序儲存結構和鏈式儲存結構的表在java語言中的實現.   ArrayList提供了一種可增長陣

C++ 雙向連結串列簡單實現通訊錄

#include<iostream> #include<fstream> #include <stdlib.h> #include<string> using namespace std; typedef struct Director

【劍指Offer學習】【試題56:連結串列中環的入口結點】

題目:一個連結串列中包含環,如何找出環的入口結點? 解題思路   可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標

1.6 python資料結構雙向連結串列/迴圈連結串列——以OrderedDict資料結構為例

在連結串列這一部分的最後,我們以python中十分強大的collections包中的OrderedDict為例,看一下雙向迴圈列表的功能實現。 OrderedDict 它提供了有序的dict結構,因此他不是常規的雜湊雜湊表,為了保證儲存物件有序,它用連結串列實現了這一功能,

C++演算法雙向連結串列的程式碼

工作閒暇時間,把程式碼過程較好的程式碼片段收藏起來,下邊資料是關於C++演算法之雙向連結串列的程式碼,應該是對各朋友有些用處。  typedef struct _DOUBLE_LINK_NODE { int data; }DOUBLE_LINK_NODE; 複製程式碼(2

劍指Offer試題24 反轉連結串列

輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。 牛客網提交程式碼: /** * struct ListNode { * int val; * struct ListNode *next; * ListNode(int x)

C語言雙向連結串列

為了克服單向性的缺點,雙向連結串列得到應用。 typedef struct link { int data; struct link* prev; //比起單向連結串列,多了指向前個節點的指標 struct link* next; }link,*link_str;

劍指Offer試題:14.連結串列的倒數第k個節點

PS:這是一道出境率極高的題目,記得去年參加校園招聘時我看到了3次,但是每次寫的都不完善。 一、題目:連結串列的倒數第k個節點 題目:輸入一個連結串列,輸出該連結串列中倒數第k個結點。為了符合大多數人的習慣,本題從1開始計數,即連結串列的尾結點是倒數第1個結點。例如一個連結串列有6個結點,從頭結點開始

劍指Offer試題56:連結串列中環的入口節點 Java實現

/************************************************************** * Copyright (c) 2016, * All rights reserved. * 版 本 號:v1.0

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

歡迎轉載,請附出處: http://blog.csdn.net/as02446418/article/details/47114711 最近重新複習了一些基礎的資料結構,發覺自己好多已經淡忘了,索性重新撿起來以前的知識,今天筆者回顧了一下連結串列的知識,用J

試題】 求連結串列倒數第K個節點

題目:輸入一個連結串列輸出連結串列中的第K個節點,(計數從1開始),連結串列節點定義如下: //定義結構 struct ListNode { ListNode() :_next(NULL) ,_data(0) {} ListNode *_next; int

資料結構學習雙向連結串列結構

注:本文的主要目的是為了記錄自己的學習過程,也方便與大家做交流。轉載請註明來自:         在前面總結的單向連結串列結構的基礎上,現在開始著手實踐實踐雙向連結串列結構,如果充分理解了單向連結串列資料結構,那對雙向連結串列結構的理解也就不再困難,換個角度而言,雙向連

一步一步寫演算法(雙向連結串列

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】     前面的部落格我們介紹了單向連結串列。那麼我們今天介紹的雙向連結串列,顧名思義,就是資料本身具備了左邊和右邊的雙向指標。雙向連結串列相比較單向連結串列,主要有下

試題56:連結串列中環的入口節點

      題目:一個連結串列中包含環,請找出該連結串列的環的入口結點。     這道題藉助於前面的連結串列的倒數第K個節點的思想,考慮快慢指標。考慮當知道了連結串列的環中所含的節點數目,用一個快指標