原创:转载请注明
在前面介绍了单项链表,
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 最后是清空和销毁链表。
整个过程预期和测试结果一致