資料結構:雙向連結串列
原創:轉載請註明
在前面介紹了單項鍊表,
http://blog.itpub.net/7728585/viewspace-2125007/
在實際的應用中雙向連結串列應用也是非常多的,因為我本生是一名DBA,我知道的在資料庫中雙向連結串列應用非常廣泛,在雙向連結串列中
我們多了一個*prior 指向前一個節點,那麼這樣如果我們已知一個節點的指標要求得上一個節點的指標就變得非常簡單了,
時間複雜度由O(n)下降到一個常數O(1),關於這個實現函式我覺得沒必要寫了太簡單了。我準備實現如下一些函式及功能
bool makenode(int datavalue,DULNODEP* p); //makenode next and prior is NULL
void freenode(DULNODEP p); //freenode
bool initlist(LISTHEADP* p); //initlist with no node head last current pointor is NULL
void destroylist(LISTHEADP p); //destroy a list,every list thing is not live
void clearlist(LISTHEADP p);//clear a list,but head is live and head last current pointor is NULL length=0
void insfirst(LISTHEADP h,DULNODEP s);//insfirst insert one node at first postion length=0
void delfirst(LISTHEADP h); //delete first node current_point to next node
void inslast(LISTHEADP h,DULNODEP s); //inslast insert one node at last postion
void dellast(LISTHEADP h) ; //delete last node current_point to prior node
void addnode(DULNODEP inode,int postion,LISTHEADP h);//insert one node after postion
void removenode(int postion,LISTHEADP h) ;//delete node at give postion
void replacenode(int postion,LISTHEADP h,DULNODEP inode);//replace one node
void viewchain(LISTHEADP h);//show info for chain
void viewheadinfo(LISTHEADP h);//only show head info
我將上一節演示的頭結點增加了last指標指向最後一個節點,同時增加了current指標指向操作的指標。結構體如下:
typedef struct listhead
{
DULNODEP head;
DULNODEP last;
DULNODEP current;
int length;
} LISTHEAD,*LISTHEADP;
這樣我們在實現inslast和dellast的時候變得非常簡單了,而delfirst和insfirst本來就是透過head指標實現的,如果大家對棧和佇列的實現有了解,著4個函式可以用來實現他們,這個我會在隨後進行說明,這裡只考慮雙線連結串列,我基本上用註釋解釋了全部了功能下面一張圖大概看看雙向連結串列的結構,假設Noden為插入的節點就是如下,刪除也差不多沒畫
下面以程式碼的方式給出實現:
下面我們給出結果來分析:
Max chain length is:4,current_pointor is:0xd210a0,head_pointor is:0xd21080,last_pointor is:0xd210a0
node:1 values is: 3
node:2 values is: 2
node:3 values is: 1
node:4 values is: 4
Max chain length is:3,current_pointor is:0xd21060,head_pointor is:0xd21060,last_pointor is:0xd210a0
node:1 values is: 2
node:2 values is: 1
node:3 values is: 4
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1
Max chain length is:3,current_pointor is:0xd210c0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 5
node:3 values is: 1
Max chain length is:3,current_pointor is:0xd210e0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 6
node:3 values is: 1
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1
首先構造了4個節點前面3個用insfrist 這樣就是 3 2 1的排列最後一個用inslast 那麼就是 3 2 1 4 可以看到確實如此
然後使用delfrist 刪除第一個就是3 那麼剩下 2 1 4 然後使用dellast 那麼刪除 4 就是 2 1 可以看到確實如此
然後我們使用addnode 在位置1後面加入元素 5 那麼就是 2 5 1 確實如此
然後我們使用replacenode 將位置2的元素 data 5的資料換位 data為 6的資料變為 2 6 1
最後呼叫removenode將位置2的元素刪除變為了 2 1 最後是清空和銷燬連結串列。
整個過程預期和測試結果一致
在前面介紹了單項鍊表,
http://blog.itpub.net/7728585/viewspace-2125007/
在實際的應用中雙向連結串列應用也是非常多的,因為我本生是一名DBA,我知道的在資料庫中雙向連結串列應用非常廣泛,在雙向連結串列中
我們多了一個*prior 指向前一個節點,那麼這樣如果我們已知一個節點的指標要求得上一個節點的指標就變得非常簡單了,
時間複雜度由O(n)下降到一個常數O(1),關於這個實現函式我覺得沒必要寫了太簡單了。我準備實現如下一些函式及功能
bool makenode(int datavalue,DULNODEP* p); //makenode next and prior is NULL
void freenode(DULNODEP p); //freenode
bool initlist(LISTHEADP* p); //initlist with no node head last current pointor is NULL
void destroylist(LISTHEADP p); //destroy a list,every list thing is not live
void clearlist(LISTHEADP p);//clear a list,but head is live and head last current pointor is NULL length=0
void insfirst(LISTHEADP h,DULNODEP s);//insfirst insert one node at first postion length=0
void delfirst(LISTHEADP h); //delete first node current_point to next node
void inslast(LISTHEADP h,DULNODEP s); //inslast insert one node at last postion
void dellast(LISTHEADP h) ; //delete last node current_point to prior node
void addnode(DULNODEP inode,int postion,LISTHEADP h);//insert one node after postion
void removenode(int postion,LISTHEADP h) ;//delete node at give postion
void replacenode(int postion,LISTHEADP h,DULNODEP inode);//replace one node
void viewchain(LISTHEADP h);//show info for chain
void viewheadinfo(LISTHEADP h);//only show head info
我將上一節演示的頭結點增加了last指標指向最後一個節點,同時增加了current指標指向操作的指標。結構體如下:
typedef struct listhead
{
DULNODEP head;
DULNODEP last;
DULNODEP current;
int length;
} LISTHEAD,*LISTHEADP;
這樣我們在實現inslast和dellast的時候變得非常簡單了,而delfirst和insfirst本來就是透過head指標實現的,如果大家對棧和佇列的實現有了解,著4個函式可以用來實現他們,這個我會在隨後進行說明,這裡只考慮雙線連結串列,我基本上用註釋解釋了全部了功能下面一張圖大概看看雙向連結串列的結構,假設Noden為插入的節點就是如下,刪除也差不多沒畫
下面以程式碼的方式給出實現:
點選(此處)摺疊或開啟
-
標頭檔案:
-
//error(1):delfirst() error list have no
-
//error(2):getelemp() postion large than lenth or poastion = 0
-
//error(3):viewchain() list no data
-
-
#ifndef _liststr_
-
#define _liststr_
-
#define bool int
-
#define true 1
-
#define false 0
-
typedef struct dulnode //node type
-
{
-
int data; //example
-
struct dulnode *prior;
-
struct dulnode *next;
-
} DULNODE,*DULNODEP;
-
-
typedef struct listhead
-
{
-
DULNODEP head;
-
DULNODEP last;
-
DULNODEP current;
-
int length;
-
} LISTHEAD,*LISTHEADP;
-
-
#define SIZENODE sizeof(DULNODE)
-
#define SIZELISTHEAD sizeof(LISTHEAD)
-
-
bool makenode(int datavalue,DULNODEP* p); //makenode next and prior is NULL
-
void freenode(DULNODEP p); //freenode
-
bool initlist(LISTHEADP* p); //initlist with no node head last current pointor is NULL
-
void destroylist(LISTHEADP p); //destroy a list,every list thing is not live
-
void clearlist(LISTHEADP p);//clear a list,but head is live and head last current pointor is NULL length=0
-
void insfirst(LISTHEADP h,DULNODEP s);//insfirst insert one node at first postion length=0
-
void delfirst(LISTHEADP h); //delete first node current_point to next node
-
void inslast(LISTHEADP h,DULNODEP s); //inslast insert one node at last postion
-
void dellast(LISTHEADP h) ; //delete last node current_point to prior node
-
void addnode(DULNODEP inode,int postion,LISTHEADP h);//insert one elem after postion
-
void removenode(int postion,LISTHEADP h) ;//delete elem at give postion
-
void replacenode(int postion,LISTHEADP h,DULNODEP inode);//replace one node
-
void viewchain(LISTHEADP h);//show info for chain
-
void viewheadinfo(LISTHEADP h);//only show head info
-
- #endif
點選(此處)摺疊或開啟
-
功能函式檔案:
-
#include<stdlib.h>
-
#include<stdio.h>
-
#include <string.h>
-
#include"dulnode.h"
-
-
static DULNODEP getelemp(const LISTHEADP h,int postion) ;
-
-
//makenode
-
bool makenode(int datavalue,DULNODEP* p)
-
{
-
*p = (DULNODEP) malloc (SIZENODE);
-
if(!(*p))
-
{
-
return false;
-
}
-
else
-
{
-
memset(*p,0,SIZENODE);
-
(*p)->data = datavalue;
-
(*p)->next = NULL;
-
(*p)->prior = NULL;
-
return true;
-
}
-
}
-
-
//freenode
-
-
void freenode(DULNODEP p)
-
{
-
free(p);
-
}
-
-
//initlist with no node
-
-
bool initlist(LISTHEADP* p)
-
{
-
*p = (LISTHEADP)malloc(SIZELISTHEAD);
-
if(!*p)
-
{
-
return false;
-
}
-
else
-
{
-
memset(*p,0,SIZELISTHEAD);
-
(*p)->head = NULL;
-
(*p)->last = NULL;
-
(*p)->current = NULL;
-
(*p)->length = 0;
-
return true;
-
}
-
}
-
//destroy a list,every list thing is not live
-
void destroylist(LISTHEADP p)
-
{
-
DULNODEP npc;
-
DULNODEP npn;
-
int i = 0;
-
-
if(npc = p->head)
-
{
-
npn = p->head->next;
-
for(i=0;i<p->length;i++)
-
{
-
free(npc);
-
npc = npn;
-
if(npn) //last one is null null->next will
-
{
-
npn = npn->next;
-
}
-
}
-
}
-
-
free(p);
-
}
-
//clear a list,but head is live
-
void clearlist(LISTHEADP p)
-
{
-
DULNODEP npc;
-
DULNODEP npn;
-
int i = 0;
-
-
if(npc = p->head)
-
{
-
npn = p->head->next;
-
for(i=0;i<p->length;i++)
-
{
-
free(npc);
-
npc = npn;
-
if(npn) //last one is null null->next will
-
{
-
npn = npn->next;
-
}
-
}
-
}
-
p->head = NULL;
-
p->last = NULL;
-
p->current = NULL;
-
p->length = 0;
-
}
-
-
//insfirst insert one node at first postion
-
-
void insfirst(LISTHEADP h,DULNODEP s)
-
{
-
if(!(h->head)) //list is empty or not
-
{
-
h->head = s;
-
h->last = s;
-
h->current = s;
-
h->length++;
-
}
-
else
-
{
-
h->head->prior = s;
-
s ->next = h->head;
-
h->head = s;
-
h->current = s;
-
h->length++;
-
-
}
-
-
}
-
-
-
//delfirst
-
void delfirst(LISTHEADP h) //delete first node current_point to next node
-
{
-
DULNODEP p;
-
if(!(h->head))
-
{
-
printf("error(1):delfirst() error list have no node!\n");
-
exit(1);
-
}
-
else if(!(h->head->next)) //only one node
-
{
-
free(h->head);
-
h->head = NULL;
-
h->current = NULL;
-
h->last = NULL;
-
h->length--;
-
}
-
else
-
{
-
p = h->head ;
-
h->head->next->prior = NULL;
-
h->head = h->head->next;
-
h->current = h->head;
-
h->length--;
-
free(p);
-
}
-
}
-
-
-
//inslast insert one node at last postion
-
-
void inslast(LISTHEADP h,DULNODEP s)
-
{
-
if(!(h->head)) //list is empty or not
-
{
-
h->head = s;
-
h->last = s;
-
h->current = s;
-
h->length++;
-
}
-
else
-
{
-
h->last->next = s;
-
s->prior = h->last;
-
h->last = s;
-
h->current = s;
-
h->length++;
-
}
-
}
-
-
-
-
//dellast
-
-
void dellast(LISTHEADP h) //delete last node current_point to prior node
-
{
-
DULNODEP p;
-
if(!(h->head))
-
{
-
printf("error(1):delfirst() error list have no node!\n");
-
exit(1);
-
}
-
else if(!(h->head->next)) //only one node
-
{
-
free(h->head);
-
h->head = NULL;
-
h->current = NULL;
-
h->last = NULL;
-
h->length--;
-
}
-
else
-
{
-
p = h->last ;
-
h->last->prior->next = NULL;
-
h->last = p->prior;
-
h->current = p->prior;
-
h->length--;
-
free(p);
-
}
-
}
-
-
-
static DULNODEP getelemp(const LISTHEADP h,int postion)
-
{
-
int i=0;
-
DULNODEP p;
-
if(postion > h->length || postion ==0 )
-
{
-
printf("error(2):getelemp() postion large than lenth or poastion = 0\n");
-
exit(2);
-
}
-
p = h->head;
-
-
while(i<postion-1)
-
{
-
i++;
-
p = p->next;
-
}
-
return p;
-
}
-
-
//addnode add one node after give postion
-
void addnode(DULNODEP inode,int postion,LISTHEADP h) //insert one elem after postion
-
{
-
DULNODEP p;
-
p = getelemp(h,postion);
-
if(!p->next) //last node?
-
{
-
p->next = inode;
-
inode->prior = p;
-
inode->next = NULL;
-
h->last = inode;
-
h->current = inode;
-
}
-
else
-
{
-
inode->prior = p;
-
inode->next = p->next;
-
p->next->prior = inode;
-
p->next = inode;
-
h->current = inode;
-
}
-
h->length++;
-
}
-
-
//removenode remove one node at postion and current point to next postion
-
-
void removenode(int postion,LISTHEADP h) //delete elem at give postion
-
{
-
DULNODEP p;
-
p = getelemp(h,postion);
-
-
if(postion == 1 && !(p->next)) //node one and only one node
-
{
-
h->head = NULL;
-
h->current = NULL;
-
h->last = NULL;
-
free(p);
-
}
-
else if(postion == 1) //node one?
-
{
-
p->next->prior = NULL;
-
h->head = p->next;
-
h->current = h->head;
-
free(p);
-
}
-
else if(!(p->next)) //last node?
-
{
-
h->current = NULL;
-
h->last = p->prior;
-
p->prior->next = NULL;
-
free(p);
-
}
-
else
-
{
-
h->current = p->next;
-
p->next->prior = p->prior;
-
p->prior->next = p->next;
-
free(p);
-
}
-
h->length--;
-
}
-
-
-
//replacenode replace one node
-
-
-
void replacenode(int postion,LISTHEADP h,DULNODEP inode)
-
{
-
DULNODEP p;
-
p = getelemp(h,postion);
-
-
if(postion == 1 && !(p->next)) //node one and only one node
-
{
-
h->head = inode;
-
h->current = inode;
-
h->last = inode;
-
free(p);
-
}
-
else if(postion == 1)
-
{
-
inode->next = h->head->next;
-
h->head->next->prior = inode;
-
h->head = inode;
-
h->current = inode;
-
free(p);
-
}
-
else if(!(p->next))
-
{
-
inode->prior = p->prior;
-
p->prior->next = inode;
-
h->current = inode;
-
h->last = inode;
-
free(p);
-
}
-
else
-
{
-
inode->prior = p->prior;
-
inode->next = p->next;
-
p->prior->next = inode;
-
p->next->prior = inode;
-
h->current = inode;
-
free(p);
-
}
-
}
-
-
-
void viewchain(LISTHEADP h)
-
{
-
int i=1;
-
DULNODEP p;
-
p = h->head;
-
if(!p)
-
{
-
printf("error(3):viewchain() list no data\n");
-
exit(3);
-
}
-
-
printf("Max chain length is:%d,current_pointor is:%p,head_pointor is:%p,last_pointor is:%p\n",h->length,h->current,h->head,h->last);
-
do
-
{
-
printf("node:%d values is: %d\n",i,p->data);
-
i++;
-
-
}while(p=p->next);
-
}
-
-
void viewheadinfo(LISTHEADP h)
-
{
-
-
printf("Max chain length is:%d,current_pointor is:%p,head_pointor is:%p,last_pointor is:%p\n",h->length,h->current,h->head,h->last);
- }
點選(此處)摺疊或開啟
-
主函式檔案:
-
#include<stdlib.h>
-
#include<stdio.h>
-
#include"dulnode.h"
-
-
-
-
int main(void)
-
{
-
LISTHEADP headp=NULL;
-
DULNODEP p1=NULL;
-
DULNODEP p2=NULL;
-
DULNODEP p3=NULL;
-
DULNODEP p4=NULL;
-
-
DULNODEP p5=NULL;
-
DULNODEP p6=NULL;
-
-
if(!(initlist(&headp)))
-
{
-
printf("initlist error\n");
-
}
-
if(!(makenode(1,&p1)))
-
{
-
printf("makenode error\n");
-
}
-
if(!(makenode(2,&p2)))
-
{
-
printf("makenode error\n");
-
}
-
if(!(makenode(3,&p3)))
-
{
-
printf("makenode error\n");
-
}
-
if(!(makenode(4,&p4)))
-
{
-
printf("makenode error\n");
-
}
-
-
if(!(makenode(5,&p5)))
-
{
-
printf("makenode error\n");
-
}
-
-
if(!(makenode(6,&p6)))
-
{
-
printf("makenode error\n");
-
}
-
-
insfirst(headp,p1);
-
insfirst(headp,p2);
-
insfirst(headp,p3);
-
inslast(headp,p4);
-
-
viewchain(headp);
-
-
delfirst(headp);
-
viewchain(headp);
-
dellast(headp);
-
viewchain(headp);
-
-
addnode(p5,1,headp);
-
viewchain(headp);
-
replacenode(2,headp,p6);
-
viewchain(headp);
-
removenode(2,headp);
-
viewchain(headp);
-
clearlist(headp);
- destroylist(headp);
-
return 0;
-
- }
下面我們給出結果來分析:
Max chain length is:4,current_pointor is:0xd210a0,head_pointor is:0xd21080,last_pointor is:0xd210a0
node:1 values is: 3
node:2 values is: 2
node:3 values is: 1
node:4 values is: 4
Max chain length is:3,current_pointor is:0xd21060,head_pointor is:0xd21060,last_pointor is:0xd210a0
node:1 values is: 2
node:2 values is: 1
node:3 values is: 4
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1
Max chain length is:3,current_pointor is:0xd210c0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 5
node:3 values is: 1
Max chain length is:3,current_pointor is:0xd210e0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 6
node:3 values is: 1
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1
首先構造了4個節點前面3個用insfrist 這樣就是 3 2 1的排列最後一個用inslast 那麼就是 3 2 1 4 可以看到確實如此
然後使用delfrist 刪除第一個就是3 那麼剩下 2 1 4 然後使用dellast 那麼刪除 4 就是 2 1 可以看到確實如此
然後我們使用addnode 在位置1後面加入元素 5 那麼就是 2 5 1 確實如此
然後我們使用replacenode 將位置2的元素 data 5的資料換位 data為 6的資料變為 2 6 1
最後呼叫removenode將位置2的元素刪除變為了 2 1 最後是清空和銷燬連結串列。
整個過程預期和測試結果一致
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2125114/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 資料結構——雙向連結串列資料結構
- 資料結構--陣列、單向連結串列、雙向連結串列資料結構陣列
- 資料結構之雙向連結串列資料結構
- 資料結構實驗之連結串列九:雙向連結串列資料結構
- Linux 核心資料結構:雙向連結串列Linux資料結構
- 資料結構(雙向連結串列的實現)資料結構
- 畫江湖之資料結構【第一話:連結串列】雙向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 雙向連結串列資料結構
- javascript中的連結串列結構—雙向連結串列JavaScript
- 連結串列-雙向連結串列
- 資料結構-雙向連結串列(Python實現)資料結構Python
- 資料結構學習(C++)——雙向連結串列 (轉)資料結構C++
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- 雙向連結串列
- 結構與演算法(03):單向連結串列和雙向連結串列演算法
- python 資料結構之雙向連結串列的實現Python資料結構
- python演算法與資料結構-雙向連結串列(40)Python演算法資料結構
- C語言資料結構:雙向連結串列的增刪操作C語言資料結構
- 實戰資料結構(5)_雙向迴圈連結串列的基本操作資料結構
- 畫江湖之資料結構【第一話:連結串列】單向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 單向連結串列資料結構
- 【資料結構與演算法學習】線性表(順序表、單連結串列、雙向連結串列、迴圈連結串列)資料結構演算法
- 【資料結構】雙迴圈連結串列(c++)資料結構C++
- JS資料結構第三篇---雙向連結串列和迴圈連結串列之約瑟夫問題JS資料結構
- 實現雙向連結串列
- 資料結構-連結串列資料結構
- 資料結構 - 連結串列資料結構
- 連結串列-資料結構資料結構
- 資料結構--連結串列資料結構
- 資料結構—連結串列資料結構
- 資料結構與演算法(三) -- 線性表之雙向連結串列資料結構演算法
- Java學習筆記:資料結構之線性表(雙向連結串列)Java筆記資料結構
- C語言資料結構:雙向迴圈連結串列的增刪操作C語言資料結構
- 資料結構之php實現單向連結串列資料結構PHP
- 資料結構-單連結串列、雙連結串列資料結構
- 資料結構_連結串列_單向迴圈連結串列 & 雙向連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- JavaScript資料結構--連結串列JavaScript資料結構
- 資料結構之「連結串列」資料結構