线性表-双向链表的简单知识
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;
}
不过还是先贴出结构体:
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; }
相关文章推荐
- 简单实现双向循环链表
- 简单双向链表(C++模版技术实现)
- 线性表实现:顺序表、链表、循环链表、双向循环链表
- (C++版)链表(三)——实现双向链表的创建、插入、删除等简单操作
- 一、(2)C++ 实现简单的线性表(链式存储结构 - 单链表)
- 一个简单的双向循环链表的实现
- C++ 双向链表的简单操作
- java 线性表---------双向链表(源代码)
- STL中双向链表的简单实现
- 一个简单的双向链表
- 数据结构复习 之 一个简单双向链表的实现
- 和菜鸟一起学linux之双向链表list head的简单实例
- 和菜鸟一起学linux之双向链表list head的简单实例
- Linux双向链表(五)——简单使用示例
- 双向链表的简单操作
- 程序一:带头结点双向链表的简单实现
- 双向循环链表简单实现
- 线性表16:双向链表 - 数据结构和算法21
- (C语言版)链表(四)——实现双向循环链表创建、插入、删除、释放内存等简单操作
- 双向链表的简单实现