C双向链表学习笔记
语言:C语言
编译环境:VC6.0
今天学习了Kenneth A.Reek著的《C和指针》一书,从中学习到了新知识,也发现了新问题,在这里做一下记录
首先先看一下代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE
{
struct NODE *fwd;
struct NODE *bwd;
int val;
}Node;
Node *rootp;
int dll_insert(register Node *rootp,int val)
{
register Node *this1; //新节点之前的那个节点
register Node *next; //新节点之后的那个节点
register Node *newnode;//新节点
for(this1 = rootp;(next = this1->fwd) != NULL;this1 = next)
{
if(next->val == val)
return 0;
if(next->val > val)
break;
}
newnode = (Node *)malloc(sizeof(Node));
if(newnode == NULL)
return -1;
newnode->val = val;
newnode->fwd = next;
this1 -> fwd = newnode;
if(this1 != rootp)
newnode -> bwd = this1;
else
newnode -> bwd = NULL;
if(next != NULL)
next -> bwd = newnode;
else
rootp -> bwd = newnode;
return 1;
}
int Link_Head_Init()
{
rootp = (Node *)malloc(sizeof(Node));
if(rootp == NULL)
{
printf("Init sb!\n");
return -1;
}
rootp->fwd = NULL;
rootp->bwd = NULL;
rootp->val = 0;
printf("Init OK!\n");
return 1;
}
void main()
{
Node *this2;
if(Link_Head_Init() == -1)
printf("Init OK!\n");
dll_insert(rootp,1);
dll_insert(rootp,3);
dll_insert(rootp,6);
dll_insert(rootp,8);
dll_insert(rootp,2);
dll_insert(rootp,1);
dll_insert(rootp,4);
dll_insert(rootp,9);
dll_insert(rootp,10);
dll_insert(rootp,7);
dll_insert(rootp,13);
dll_insert(rootp,14);
this2 = rootp;
while(this2 != NULL)
{
printf("%d\n",this2->val);
this2 = this2->fwd;
}
while(1);
}
一、出现的问题:
1.根节点需要分配空间,并做初始化;
2.出现please enter the path for DBGHEAP.C这个错误的原因是因为但不调试到库函数时,这个函数没有源代码。可以用F10跳过。
二、双向链表知识:
1.双向链表中最重要的是在这个链表中添加一个节点,首先我们看一下把一个节点插入到链表时,可能出现的4种情况:
a.新值可能必须插入到链表的中间位置
b.新值可能必须插入到链表的起始位置
c.新值可能必须插入到链表的结束位置
d.新值可能必须插入到链表的起始位置,又可能必须插入到链表的结束位置(既原链表为空)
2.建立一个双向链表的步骤:
a.声明一个链表类型
typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int val; }Node;
其中fwd是指向当前节点的前一节点指针,bwd是指向当前节点的后一节点指针,val为节点保存的值。
b.定义根节点,并初始化它:
Node *rootp;
int Link_Head_Init()
上面的程序定义一个根节点rootp,并利用int Link_Head_Init()函数来将其初始化,在这个函数里,malloc为动态分配内存函数,给rootp分配的空间大小问哦Node的大小,在这里需要注意的是一定要检查是否分配成功。后面三句话为这个根节点初始化内容,由于链表为空,所以将器fwd和bwd初始化为NULL。{ rootp = (Node *)malloc(sizeof(Node)); if(rootp == NULL) { printf("Init sb!\n"); return -1; } rootp->fwd = NULL; rootp->bwd = NULL; rootp->val = 0; printf("Init OK!\n"); return 1; }
c.插入节点函数:
在这个函数里,首先定义了三个节点类型的指针,分别表示为指向新节点之前的那个节点,新节点之后的那个节点和新节点,然后利用for循环遍历整个链表,由于这里采用了升序排列,所以找到比当前值大的那个节点,退出for循环,如果发现了和当前值一样的节点,则不添加新节点。然后利用malloc函数给新节点分配空间,将新节点的fwd指向next节点,将当前节点this1指向新节点。然后开始判断当前节点是不是根节点,如果是,就将新节点的bwd指向当前节点this,否则指向NULL,又判断是不是在链表的末尾添加新节点,如果是则将根节点的bwd指向新节点newnode,否则将下一个节点next的bwd指向newnode。int dll_insert(register Node *rootp,int val) { register Node *this1; //新节点之前的那个节点 register Node *next; //新节点之后的那个节点 register Node *newnode;//新节点 for(this1 = rootp;(next = this1->fwd) != NULL;this1 = next) { if(next->val == val) return 0; if(next->val > val) break; } newnode = (Node *)malloc(sizeof(Node)); if(newnode == NULL) return -1; newnode->val = val; newnode->fwd = next; this1 -> fwd = newnode; if(this1 != rootp) newnode -> bwd = this1; else newnode -> bwd = NULL; if(next != NULL) next -> bwd = newnode; else rootp -> bwd = newnode; return 1; }
(未完待续)