线性表的链式存储(单链表)

#include<iostream>
#include<stdlib.h>
using namespace std;


typedef struct LNode{
	int data;//数据元素
	struct LNode *next; //指向后续结点 
}LinkNode;

//线性表 -————单链表 
int main(){
	//函数声明
	void GreateListF(LinkNode *&L,int a[],int n);//头插法,输入输出是相反的 
	void GreateListR(LinkNode *&L,int a[],int n);//尾插法,输入输出顺序相同
	void InitList(LinkNode *&L);//初始化
	void DestoryList(LinkNode *&L);//销毁线性表
	bool ListEmpty(LinkNode *L);//判断是否为空表
	int ListLength(LinkNode *L);//线性表的长度
	void DisLinkNode(LinkNode *L);//输出线性表
	bool GetElem(LinkNode *L,int i,int &e);//求线性表第i个位置的元素
	int LocateElem(LinkNode *L,int e);//查找元素的位置(逻辑号,线性表是从1开始) 
	bool ListInset(LinkNode *&L,int i,int e);//在第i个位置插入数据元素
	bool ListDelete(LinkNode *&L,int i,int &e);//删除第i个位置的数据元素
 	LinkNode *L;
 	int e;//用于接收函数返回的数值 
 	int a[]={1,2,3,4,5};
 	GreateListR(L,a,5);
 	if(ListEmpty(L)){
 		cout<<"线性表为空"<<'\n';
	 }else{
		cout<<"线性表不为空"<<'\n';
	 } 
	cout<<"线性表的长度为:"<<ListLength(L)<<endl;
	DisLinkNode(L);//打印线性表 
	ListInset(L,2,10);//在第2的位置插入一个元素,注意线性表从1开始 
	cout<<"插入元素后的线性表:"<<endl; 
	DisLinkNode(L);
	ListDelete(L,3,e);
 	DestoryList(L);//销毁线性表 
 	cout<<"删除成功"<<endl;
	return 0; 
} 

/*---------------------------------------------------------------------------*/
//初始化
void InitList(LinkNode *&L){
	L = new LinkNode; //创建头结点 
	L->next = NULL; //next域置为NULL 
} 
/*---------------------------------------------------------------------------*/
//头插法,输入输出是相反的 
void GreateListF(LinkNode *&L,int a[],int n){
	LinkNode *p;
	L = new LinkNode;
	L->next=NULL;
	for(int i =0;i<n;i++){
		p = new LinkNode;
		p->data = a[i];
		//将节点p插入到原节点之前、头结点之后 例:s->q->...改为:s->p->q->...
		p->next = L->next;
		L->next = p; 
	}
} 
/*---------------------------------------------------------------------------*/
void GreateListR(LinkNode *&L,int a[],int n){
	LinkNode *p,*r;//*r尾指针,始终指向最后一个结点 
	L = new LinkNode;
	L->next = NULL;
	r=L;//开始将头结点作为尾结点
	/*
		int n = sizeof(a);//获得数组的长度,注意,不能直接在函数体里面使用sizeof方法,因为形参数组的长度不确定 
		当把数组作为函数的参数时,你无法在程序运行时通过数组参数本身告诉函数该数组的大小,因为函数的数组参数相
	当于指向该数组第一个元素的指针。这意味着把数组传递给函数的效率非常高,也意味着程序员必须通过某种机制告诉
	函数数组参数的大小。
	*/
	for(int i =0;i<n;i++){
		p = new LinkNode;
		p->data = a[i];
		r->next = p;
		r = p;//改变尾指针r的指向 
	} 
	r->next = NULL;//函数结束时,就r的next域置为NULL 
}
/*---------------------------------------------------------------------------*/
//疑问:线性表链式存储,在第2个位置插入,是按:1 2,还是按:0 1 2 的顺序插入?答案:下标为:1的位置 
//在第i个位置插入数据元素,采用:头插法 
bool ListInset(LinkNode *&L,int i,int e){
	int j = 0;
	LinkNode  *p,*q=L;  //q指向L的首节点 
	while(q!=NULL&&j<i-1){   //找到第i-1个结点 
		q = q->next;
		j++;
	}
	if(q == NULL){
		return false;//插入位错误 
	}else{
		p = new LinkNode;	//创建新节点 
		p->data = e;		//赋:数值 
		p->next = q->next;  //将节点p插入到节点q之后,也就是第i个位置 
		q->next = p;		//q指向p节点 
		return true;
	}
} 

/*---------------------------------------------------------------------------*/
//删除第i个位置的数据元素
bool ListDelete(LinkNode *&L,int i,int &e){
	int j = 0;//用于判断i是否在链表内
	LinkNode *p,*q=L;
	while(j<i-1&&q!=NULL){  //找到第i-1个结点 
		q = q->next;
		j++;
	} 
	if(q==NULL){//若未找到值,则返回:false
		return false; 
	}else{
		p = q->next; //是p指向第i个结点 
		if(p ==NULL){//如果不存在第i个结点 
			return false;
		}else{
			e = p->data;//将该结点的数值域保存
			q->next = p->next;//取消 q结点(也就是第i个结点的前后链接
			delete p;//销毁p,因为q结点不再指向p,而是指向原来p结点的下一个结点 
			return true; 
		} 
	} 
} 
/*---------------------------------------------------------------------------*/
//输出 
void DisLinkNode(LinkNode *L){
	LinkNode *p;
	p = L->next; //p指向L:首节点 
	while(p!=NULL){
		cout<<p->data<<" ";
		p=p->next;//移动指针 
	} 
	cout<<'\n'; 
} 
/*---------------------------------------------------------------------------*/
//销毁线性表 
void DestoryList(LinkNode *&L){
	 LinkNode *pre=L, *p=L->next; //pre指向结点L的前驱结点(首结点)
	 while(p!=NULL){
	 	 delete pre;
		 pre = p;		//p和pre同时往后移动 
		 p = pre->next; 	
	 } 
	 delete pre;
} 
/*---------------------------------------------------------------------------*/
//判断为空 
bool ListEmpty(LinkNode *L){
	return L->next==NULL; 
} 
/*---------------------------------------------------------------------------*/
//获取线性表的长度 
int ListLength(LinkNode *L){
	int length=0;
	LinkNode *p=L;//p指向头结点,length置为0(头结点的序号为:0) 
	while(p->next!=NULL){
		length++;
		p = p->next;
	} 
	return length;
} 
/*---------------------------------------------------------------------------*/
//求线性表第i个位置的元素
bool GetElem(LinkNode *L,int i,int &e){
	LinkNode *p=L;
	int j=0;
	if(i<0){
		return false;
	} 
	while(j<i&&p->next!=NULL){
		j++;
		p = p->next; 
	}
	if(p==NULL){
		return false; 
	}else{
		e = p->data;
		return true;
	}
}
/*---------------------------------------------------------------------------*/
//查找元素:e的位置(逻辑号,线性表是从1开始) 
int LocateElem(LinkNode *L,int e){
	int  j = 1;
	LinkNode *p = L;
	while(p!=NULL&&p->data!=e){
		p = p->next;
		j++;
	}
	if(p!=NULL){
		return j;//如果存在x元素,则返回逻辑号:j 
	}else{
		return 0;//如不存在,则返回:0 
	}
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值