您的位置:首页 > 其它

线性表-双向链表的简单知识

2015-02-09 18:31 316 查看
前面先贴出我之前才学双向链表写的总结,也许更贴近我才接触的感受,虽然也没过去多久。贴出的代码则是我重新写的和之前写的还是有点不一样(写的要稍微好一点点点),前面这就作为代码思想的注释吧,而且我只列出当时重点怎么理解的部分。

不过还是先贴出结构体:

typedef struct Node {

int data;

structNode *prior;//前驱

structNode *next;//后继

}Node, *pNode;

the past:

双向链表对比与单向链表,具有前驱和后继,双向链表还是蛮有趣的,因为他从前往后和从后往前都可以知道链表的值,我也看了很久。从头开始学习算法真心不容易,请允许我这个渣慢慢进步啊。

pNode Init() {

pNodeL = (pNode )malloc(sizeof(Node));

if(!L) {

printf("failed\n");

exit(-1);

}

L->next = L->prior = NULL;//初始化头结点的前驱后继都为空

//好像得有返回量 我用void型就写出问题 唉。。。

returnL ;

}

//头插法

//头插法在于头永远都在那里不会变 相对来说操作很死板

void PreInsert(pNode L,int item) {

pNodep = L;

pNodepNew = (pNode)malloc(sizeof(Node));

pNew->data= item;

pNew->prior= p;

pNew->next= p->next;

p->next= pNew;

return;

}

//尾插法

//我想了好久也是醉了

/*

尾插法在于每次都在最后一个节点后面插入,所以关键是怎么处理怎么设置出tail这个节点

我原先的写法:

voidTailInsert(pNode L, int item) {

pNodetail = L;

pNodepNew = (pNode)malloc(sizeof(Node));

pNew->data= item;

tail->next= pNew;

pNew->prior= tail;

pNew->next= NULL;

tail= pNew;

}

main函数里这样

pNodeL;

L= Init();

printf("\n尾插法:\n");

TailInsert(tail,8);

TailInsert(tail,9);

TailInsert(tail,1);

TailInsert(tail,2);

Traverse(L);//结果就一个数据

我的想法是每次在tail节点后插入一个新节点,然后在把最后这个新节点变成tail节点,这样不就行了么。

这段代码错误就在于pNode tail = L;这一句导致的结果就是每次执行插入函数,又特么的从开始的尾插入,

也就是永远只能插入一个数据(执行遍历就一个值)。

所以我就在想怎么让这个tail随着链表长度变化他一直在链表的最后位置。

想啊想,真特么的烦啊

本来我还想设个全局变量,把pNode L作为全局变量在放入函数里不就不会每次都变了,但那不就整个程序就变味了么唉。。

后来我就试着把pNode tail = L 去掉,然后在main函数里这样写

pNodeL;

L= Init();

pNodetail = L;

printf("\n尾插法:\n");

TailInsert(tail,8);

TailInsert(tail,9);

TailInsert(tail,1);

TailInsert(tail,2);

Traverse(L);

这样写pNode L;

L= Init();

pNodetail = L;就能让tail一直成为尾巴了,而原本的头一直没变

然后测试还特么的一个数据

想啊想

最后想到(不是凭技术想出来的)我最近写链表时遇到的,就是传引用到函数里,就是TailInsert(pNode &tail, int item)酱紫

我想了想,自我理解是因为tail直接传进去无法传回来,只能传引用才会变,只能酱紫

理解了

怎么说总算搞出来了

2015/1/12/17:19

*/

void TailInsert(pNode &tail, int item){

pNodepNew = (pNode)malloc(sizeof(Node));

pNew->data= item;

tail->next= pNew;

pNew->prior= tail;

pNew->next= NULL;

tail= pNew;

}

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef int datatype;

typedef struct Node {
datatype data;
struct Node *prior;//前驱
struct Node *next;//后继
}Node, *pNode;
//===============================
void Init(pNode &L);//初始化
void PreInsert(pNode &L, datatype item);//前插法
void TailInsert(pNode &L, datatype item);//尾插法
void DeleteNode(pNode &L, datatype &item);//删除节点
void DelteList(pNode &L);//删除链表
void Traverse(pNode L);//遍历
//==================================================
//初始化

void Init(pNode  &L) {
L = (pNode)malloc(sizeof(Node));
if(!L)
exit(-1);
L->next = L->prior = NULL ;//前驱后继均为空
return ;
}
//====================================================
//遍历
void Traverse(pNode L) {
pNode p = L->next ;
while(p) {
printf("%d ",p->data );
p = p->next ;
}
return ;
}
//======================================================
//====================================================
//只想看看前驱有没有实现
void TraversePrior(pNode L) {
pNode p = L;
if(!L->next) {
return;
}
while(p->next ) {
p = p->next ;//先遍历到最后
}
while(p != L) {//再从最后遍历到最前 真特么的矫情
printf("[%d] ",p->data );
p = p->prior ;
}
return ;
}
//======================================================
//前插法
/*	   pNew
/
L------L->next

*/
void PreInsert(pNode &L, datatype item) {
pNode pNew = (pNode )malloc(sizeof(Node));
if(!pNew)
exit(-1);
pNew->data = item;
/*插入一个新节点 无非给pNew弄个前驱后继,或者说L的后继变了,
L->next的前驱变了
*/
pNew->next = L->next;
L->next = pNew;
pNew->prior = L;

return;
}
//===========================================================
//尾插法
void TailInsert(pNode &tail, datatype item) {
pNode pNew = (pNode )malloc(sizeof(Node ));
if(!pNew )
exit(-1);
pNew->data = item;

tail->next = pNew;
pNew->prior = tail;
pNew->next = NULL ;

tail = pNew;

return;
}
//==========================================================
//从头开始删
void DeleteNode(pNode &L, datatype &item) {
pNode temp =L->next ;
item = temp->data;//删除的节点的值
temp->next->prior = temp->prior ;//节点删除了,那么她的后继需要一个前驱

temp->prior->next  = temp->next ;//她的前驱需要一个后继

free(temp);//释放
temp = NULL ;
return;

}
//===========================================================
//删除链表
void DeleteList(pNode &L) {
if(NULL == L) {
return;
}

pNode p = L->next;
while(p) {
pNode q = p;
//	printf("[%d] ",p->data);
p = p->next;
free(q);
q = NULL;
}
/*
if(p)
printf("haha");
else
printf("hehe");

if(L->next )
printf("111111");
else
printf("222222");
这中间部分就是说明p被释放了,但是L->next还是存在的,所以下面那句就是必需
的了。至于为什么L->next还是真我也不是很理解

*/
L->next = NULL;
//free(L);
//L = NULL;算了还是保留头结点吧 看你理解的意思了

return;
}

//=========================================================
int main() {
pNode p;
Init(p);
Traverse(p);
//	PreInsert(p,1);
//	PreInsert(p,2);
//	PreInsert(p,3);
//	PreInsert(p,4);
//	Traverse(p);
pNode tail = p;
TailInsert(tail,1);
TailInsert(tail,2);
TailInsert(tail,3);
TailInsert(tail,4);//tail永远是尾巴 唉 。。。
Traverse(p);
printf("\n");
printf("遍历前驱:\n");
TraversePrior(p);
printf("\n");
int item;
printf("删除节点:\n");
DeleteNode(p,item);
printf("删除的是%d \n",item);
Traverse(p);
printf("\n");
printf("清空链表:\n");
DeleteList(p);

Traverse(p);
printf("\n");

free(p);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: