题目:
构造一个单链表,实现创建、删除、插入、查找等功能。
解析:
初始化单链表,即单链表的表头指针为空
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;
}