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

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

不过还是先贴出结构体:

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;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值