链式单链表

题目:

    构造一个单链表,实现创建、删除、插入、查找等功能。

解析:

初始化单链表,即单链表的表头指针为空

void initlist(node **pnode)
{
	*pnode = NULL;
	printf("初始化成功!\n");
}

 打印链表元素,遍历链表 

//打印链表元素,遍历链表 
void printinfo(linklist list)
{
	lnode *head;
	if(head == NULL)//链表为空 
		cout<<"链表为空!"<<endl;
	//链表不为空则输出打印出元素 
	else 
	{
		cout<<"链表元素为:";
		for(head=list;head!=NULL;head=head->next)//第一个指向list
			cout<<head->data<<" ";
		cout<<endl<<endl;
	}
}

知晓链表长度创建一个线性链表

从线性表的第一个元素开始依次获取表中的数据元素,每取得一个数据元素,就为该数据元素生成一个新的链结点,将取得的数据元素的数据信息送新的结点的数据域的同时,将新结点的指针域置为NULL,然后将新的链结点插入到链表的尾部。当取第1个数据元素时,链表为空,此时只需要将新的链结点的地址传送即可 。

linklist creat(int n)
{
	linklist p,r,next = NULL;
	elemtype a;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);//获取一个数据元素 
		p = (linklist)malloc(sizeof(node));//申请一个新的结点 
		p->data = a;
		p->next = NULL;//链表末尾指针域置空 
		if(next == NULL)
			next = p;
		else
			r->next = p;//将新的结点链接在链表的尾部 
		r=p;//指针变量总是指向链表的末尾 
	} 
	return next;
}

求链表的长度(1)

首先将指针指向链表的第一个链结点,然后遍历链表,指针变量每指向一个链结点,计数器就加1,遍历结束后,计数器的数据就是链表的长度。

int length1(linklist list)
{
	linklist p = list;
	int n = 0;
	while(p!=NULL)
	{	
		n++;//计数器累加 
		p = p->next; //指针p指向下一个链结点 
	}
	return n;//返回链表的长度 
} 

求链表的长度(2)

递归结构,即每个链结点的指针域均指向一个线性链表,它所指向的链结点为该链表的第1个链结点。

int length2(linklist list)
{
	if(list!=NULL)
		return 1+length2(list->next);
	else
		return 0; 
} 

测试链表是否为空

如果指针指向的第1个链结点为NULL,则链表为空,否则链表非空。

void isempty(linklist list)
{
	if(list == NULL)
        printf("链表为空\n");
    else
    	printf("链表非空\n");
} 

确定元素item在线性链表中的位置

从链表的第1个链结点开始,依次遍历链表,查找其是否与给定值item相匹配。如果相匹配则输出item的位置,否则则输出链表中该值不存在。

linklist find(linklist list,elemtype item)
{
	linklist p = list;
	int place = 1;//计数器记录位置
	while(p !=NULL && p->data != item)//查询是否匹配
	{
		place++;
		p = p->next;
	}
	if(p !=NULL && p->data == item)
		cout<<"item的位置为:"<<place<<endl;
	else
		cout<<"item不存在!"<<endl;
}

在非空线性链表的第1个链结点前插入一个数据信息为item的链结点

首先申请一个新的链结点,将其数据信息item置于新链结点的数据域内,然后将第1个结点的指针list送入新结点的指针域内,同时将新结点的地址赋予给list,从而新结点插入链表的最前面,由此完成插入。

void insert1(linklist &list,elemtype item)
{
	//list中存放链表的首地址
	linklist p;
	p = (linklist)malloc(sizeof(node));//申请一个新的链接点
	p ->data = item;//将item送新结点的数据域
	p ->next = list;//将list送新结点的指针域
	list = p;//list指向新结点 
} 

非空线性链表的末尾插入一个数据信息为item的链接点

首先设置一个指针变量,使其指向链表的第1个链结点,然后反复执行直到其等于NULL,此时指针指向链表的末尾链结点,然后将item送入申请的新结点的数据域的同时,将新的结点的指针域置为NULL,最后将新的结点的地址送入指针变量指向的链结点的指针域中,由此完成插入。

void insert2(linklist list,elemtype item)
{
	//list存放链表的首地址
	linklist p,r;
	r = list;
	while(r->next!=NULL)
		r = r->next;//找到链表末尾结点的地址 
	p = (linklist)malloc(sizeof(node));//申请一个新的链接点
	p ->data = item;//将item送新结点的数据域
	p ->next = NULL;//新结点的指针域置为NULL 
	r ->next =p;//插入链表的末尾 
}

在线性链表中的第i个链结点后面插入一个数据信息为item的链接点

从第1个结点开始查询直到第i个结点,然后将新的结点插到它们的后面。如果不存在第i个链结点则输出不存在。如果存在第i个链结点则申请一个新的结点,然后将item送入新的结点的数据域,并且将新的结点插到第i个链结点之后,如此插入成功。

void insert4(linklist list,int i,elemtype item)
{
	linklist p,q = list;
	int j=1;
	while(j<i&&q!=NULL)
	{
		q = q ->next;
		j++; 
	}//寻找第i个链结点
	if(j!=i||q==NULL)
		printf("链表中不存在第i个链结点");
	p = (linklist)malloc(sizeof(node));//申请一个新的链结点
	p ->data = item;//将item送新结点的数据域
	p ->next = q ->next;
	q ->next = p;//将新结点插入第i个链结点之后
}

在按值有序链接的线性链表中插入一个数据信息为item的链结点

先为被插入的链结点申请一个新的链结点,然后从链表的第一个链结点开始顺序查找插入位置,在查找的过程中保留当前链结点的直接前驱结点的位置,由此进行插入。

void insert5(linklist &list,elemtype item)
{
	linklist p,q,r;
	p = (linklist)malloc(sizeof(node));
	p ->data = item;
	if(list==NULL||item<list->data)//若链表为空或者item小于第1个链结点 
	{
		p ->next = list;//将新的链结点插在链表最前面 
		list = p;//list指向被插入的新结点 
	}	
	else
	{
		q = list;
		while(q!=NULL&&item>=q->data)//寻找插入位置 
		{
			r = q;
			q = q->next;
		}
		p->next = q;
		r->next = p;//将新的链结点插在q指示的链结点后面 
	} 
}

销毁一个线性链表

设置一个指针变量,先将其指向链表的第1个链结点,然后遍历整个链表,过程中删除并释放链结点。

void deletelist(linklist &list)
{
	linklist p = list;
	while(p!=NULL)
	{
		list = p->next;//保存下一个链结点的位置
		free(p);//删除并释放当前的链结点
		p = list;//下一个链结点成为当前链结点
	}
} 

删除第k个结点

从链表第一个链结点开始,找到第k个链结点,然后删除该结点并释放空间。

lnode* getelem(linklist list,int k)
{
    lnode* s=list;
    while(k)
    {
        s=s->next;
        k--;
    }
    return s;
}

void deletelist3(linklist list,int k)
{
    lnode* p=list;
    lnode* q=NULL;
    p=getelem(list,k-1);
    q=p->next;
    p->next=q->next;
    free(q);

}

逆转一个线性链表

通过改变链结点指针域中的地址来依次改变数据元素的关系。

//逆转一个线性链表
void invert(linklist &list)
{
	linklist p,q,r;
	p = list;
	q = NULL;
	while(p!=NULL)
	{
		r = q;
		q = p;
		p = p->next;
		q->next = r;
	}
	list = q;
} 

复制一个线性链表

如果一个链表为空,则输出链表为空。如果链表非空则复制链表所指的链结点,并将该链结点的指针赋给另外一个链结点,然后复制链结点后面一个链结点,最后返回另一个链表的第1个链结点

//复制一个线性链表
linklist copy(linklist lista)
{
	linklist listb;
	if(lista==NULL)
		cout<<"链表为空"<<endl;
	else
	{
		listb = (linklist)malloc(sizeof(node));
		listb->data = lista->data;
		listb->next = copy(lista->next); 
	}
	return listb;
} 

附:源代码

#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;
typedef int elemtype;

typedef struct node
{
	elemtype data;//数据域 
	struct node *next;//指针域 
}lnode,*linklist;//定义一个线性链表的类型 

void initlist(linklist *pnode)
{
	*pnode = (linklist)malloc(sizeof(lnode));
	if(*pnode == NULL)
		printf("初始化失败\n\n");
	else
	{
		(*pnode)->next =NULL;
		printf("初始化成功!\n\n"); 
	}
}

linklist creat(int n)
{
	linklist p,r,next = NULL;
	elemtype a;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);//获取一个数据元素 
		p = (linklist)malloc(sizeof(node));//申请一个新的结点 
		p->data = a;
		p->next = NULL;//链表末尾指针域置空 
		if(next == NULL)
			next = p;
		else
			r->next = p;//将新的结点链接在链表的尾部 
		r=p;//指针变量总是指向链表的末尾 
	} 
	return next;
}

//求线性链表的长度
int length1(linklist list)
{
	linklist p = list;
	int n = 0;
	while(p!=NULL)
	{	
		n++;//计数器累加 
		p = p->next; //指针p指向下一个链结点 
	}
	return n;//返回链表的长度 
} 

//求线性链表的长度(递归)
int length2(linklist list)
{
	if(list!=NULL)
		return 1+length2(list->next);
	else
		return 0; 
} 

//测试线性链表是否为空
void isempty(linklist list)
{
	if(list == NULL)
        printf("链表为空\n");
    else
    	printf("链表非空\n");
} 

//确定元素item在线性链表中的位置
linklist find(linklist list,elemtype item)
{
	linklist p = list;
	int place = 1;
	while(p !=NULL && p->data != item)
	{
		place++;
		p = p->next;
	}
	if(p !=NULL && p->data == item)
		cout<<"item的位置为:"<<place<<endl;
	else
		cout<<"item不存在!"<<endl;
}

//在非空线性链表的第1个链结点前插入一个数据信息为item的链结点
void insert1(linklist &list,elemtype item)
{
	//list中存放链表的首地址
	linklist p;
	p = (linklist)malloc(sizeof(node));//申请一个新的链接点
	p ->data = item;//将item送新结点的数据域
	p ->next = list;//将list送新结点的指针域
	list = p;//list指向新结点 
} 

//非空线性链表的末尾插入一个数据信息为item的链接点
void insert2(linklist list,elemtype item)
{
	//list存放链表的首地址
	linklist p,r;
	r = list;
	while(r->next!=NULL)
		r = r->next;//找到链表末尾结点的地址 
	p = (linklist)malloc(sizeof(node));//申请一个新的链接点
	p ->data = item;//将item送新结点的数据域
	p ->next = NULL;//新结点的指针域置为NULL 
	r ->next =p;//插入链表的末尾 
}


//在线性链表中的第i个链结点后面插入一个数据信息为item的链接点
void insert4(linklist list,int i,elemtype item)
{
	linklist p,q = list;
	int j=1;
	while(j<i&&q!=NULL)
	{
		q = q ->next;
		j++; 
	}//寻找第i个链结点
	if(j!=i||q==NULL)
		printf("链表中不存在第i个链结点");
	p = (linklist)malloc(sizeof(node));//申请一个新的链结点
	p ->data = item;//将item送新结点的数据域
	p ->next = q ->next;
	q ->next = p;//将新结点插入第i个链结点之后
}

//在按值有序链接的线性链表中插入一个数据信息为item的链结点
linklist insert5(linklist &list,elemtype item)
{
	linklist p,q,r;
	p = (linklist)malloc(sizeof(node));
	p ->data = item;
	if(list==NULL||item<list->data)//若链表为空或者item小于第1个链结点 
	{
		p ->next = list;//将新的链结点插在链表最前面 
		list = p;//list指向被插入的新结点 
	}	
	else
	{
		q = list;
		while(q!=NULL&&item>=q->data)//寻找插入位置 
		{
			r = q;
			q = q->next;
		}
		p->next = q;
		r->next = p;//将新的链结点插在q指示的链结点后面 
	} 
	return list;
}

//销毁一个线性链表
void deletelist(linklist &list)
{
	linklist p = list;
	while(p!=NULL)
	{
		list = p->next;//保存下一个链结点的位置
		free(p);//删除并释放当前的链结点
		p = list;//下一个链结点成为当前链结点
	}
} 


lnode* getelem(linklist list,int k)
{
    lnode* s=list;
    while(k)
    {
        s=s->next;
        k--;
    }
    return s;
}

void deletelist3(linklist list,int k)
{
    lnode* p=list;
    lnode* q=NULL;
    p=getelem(list,k-1);
    q=p->next;
    p->next=q->next;
    free(q);

}

//逆转一个线性链表
void invert(linklist &list)
{
	linklist p,q,r;
	p = list;
	q = NULL;
	while(p!=NULL)
	{
		r = q;
		q = p;
		p = p->next;
		q->next = r;
	}
	list = q;
} 

//复制一个线性链表
linklist copy(linklist lista)
{
	linklist listb;
	if(lista==NULL)
		cout<<"链表为空"<<endl;
	else
	{
		listb = (linklist)malloc(sizeof(node));
		listb->data = lista->data;
		listb->next = copy(lista->next); 
	}
	return listb;
} 


//打印链表元素,遍历链表 
void printinfo(linklist list)
{
	lnode *head;
	if(head == NULL)//链表为空   
		cout<<"链表为空!"<<endl;
	//链表不为空则输出打印出元素 
	else 
	{
		cout<<"链表元素为:";
		for(head=list;head!=NULL;head=head->next)//第一个元素指向list  
			cout<<head->data<<" ";
		cout<<endl<<endl;
	}
}

int main()
{

	lnode *list = NULL; 
	elemtype length = 0,item;
	
	//测试链表是否为空
	cout<<"测试链表是否为空!"<<endl;
	isempty(list);
	
	//初始化单链表,即单链表的表头指针为空
	cout<<endl<<"初始化链表!"<<endl;
	initlist(&list);//链表初始化 
	
	//知晓链表长度创建一个线性链表
	cout<<"创建链表!"<<endl; 
	int m;//长度 
	cout<<"输入链表长度:";
	scanf("%d",&m);
	cout<<"输入数据:";
	list = creat(m);//数据元素需要接收回来赋给list 
	printinfo(list); 
	
	//求线性链表的长度
	cout<<"链表的长度:";
	cout<<length1(list)<<endl;
	
	//递归求链表的长度
	cout<<"递归求链表的长度:";
	cout<<length2(list)<<endl<<endl; 
	
	//测试链表是否为空
	cout<<"测试链表是否为空!"<<endl;
	isempty(list);
	
	//确定元素item在线性链表中的位置
	cout<<endl<<"确定item在链表中的位置!"<<endl; 
	cout<<"输入item:";
	scanf("%d",&item); 
	find(list,item);
	
	//在非空线性链表的第1个链结点前插入一个数据信息为item的链结点
	cout<<endl<<"在链表第1个链结点插入item!"<<endl; 
	cout<<"输入item:";
	scanf("%d",&item);
	insert1(list,item);
	printinfo(list); 
	
	//非空线性链表的末尾插入一个数据信息为item的链接点
	cout<<endl<<"在链表末尾插入item!"<<endl; 
	cout<<"输入item:";
	scanf("%d",&item);
	insert2(list,item);
	printinfo(list); 
	
	//在线性链表中的第i个链结点后面插入一个数据信息为item的链接点
	cout<<endl<<"在链表中的第i个链结点后面插入item!"<<endl; 
	cout<<"输入item:";
	scanf("%d",&item);
	elemtype i;
	cout<<"输入i:";
	scanf("%d",&i);
	insert4(list,i,item);
	printinfo(list);

	//在按值有序链接的线性链表中插入一个数据信息为item的链结点
	cout<<endl<<"在按值有序链接的线性链表中插入item!"<<endl; 
	cout<<"输入item:";
	scanf("%d",&item);
	list = insert5(list,item);
	printinfo(list);
	
	
	//删除第 k 个节点
	cout<<endl<<"删除第k个结点!"<<endl;
	elemtype k;
	cout<<"输入k:";
	cin>>k;
	deletelist3(list,k);
	printinfo(list);
	
	//逆转一个线性链表
	cout<<endl<<"逆转链表!"<<endl; 
	invert(list);
	printinfo(list);
	
	//复制一个线性链表
	cout<<"复制链表!"<<endl; 
	copy(list);
	printinfo(list);

    //销毁一个线性链表
	cout<<endl<<"销毁链表!"<<endl;
	deletelist(list);
	isempty(list);
	
	return 0;
}             

                                           

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值