C++程序设计 有关于链表的操作
发布网友
发布时间:2022-11-10 12:54
我来回答
共3个回答
热心网友
时间:2023-11-24 17:54
不要照着书上学那些生搬硬套的东西。首先你得明白链表是什么,插入和删除的算法是很简单的。链表就是一方面存着数据,另一方面存着下一个节点的地址的数据结构,这样就可以从头节点开始查看所有节点的数据。既然存放的是地址,插入的时候你需要做的是谁存放新的节点的地址,新的节点存放谁的地址。删除的时候,就是要把这个节点去掉,既然这个节点不在了,就如链条去掉一环,那么需要把去掉的节点前边的环和后边的环连起来,不然链表就断了追问
谢谢您啦
追答问题1:
if (phead == NULL)
{
phead = pnode; // 这里phead是一个指针,存放第一个节点的地址,因为链表为空,所以插入的
// pnode成为头节点,头指针只是一个指针
return; // 因为初始化的时候新节点中指向next指针赋了空值,所以这里不需要再做
}
问题2:
这里的操作说明这个链表是个整形数据的顺序表,节点按升序排序,所以插入的时候要把新节点插入到合适的位置,保证整个链表有序。这一步发现新节点的值小于头节点的值,所以要把新节点当成头节点,而新节点指向原来的头节点。由于头指针保存了头节点的地址,所以要先把新节点的next指针保存原来的头节点的地址,然后把新节点的地址赋给头指针,从而使新节点变成头节点
问题3:
r和q都是两个节点类型的指针。
问题4:
r=q;
q=q->next;
这里首先用r保存当前q的值,然后q指向下一个节点。最终r是上一个节点,q是当前节点。这样,若果需要把新节点插入q之前,那么就需要r指向新节点,新节点指向q。
问题5:
你的理解是对的。就是让r指向pnode,让pnode指向q
热心网友
时间:2023-11-24 17:55
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef struct node
{
int x;
struct node *next;
}Node;
void play(Node *p)//显示每个元素
{
p=p->next;
while(p)
{
cout<<p->x<<endl;
p=p->next;
}
}
void built(Node *head)//建立链表1
{
int n,i;
Node *p=head;
cout<<"请输入要加入的元素个数"<<endl;
cin>>n;
if(n)
{
cout<<"请输入"<<n<<"个数"<<endl;
for(i=0;i<n;i++)//为n个元素分配空间
{
p->next=new Node;
cin>>p->next->x;
p=p->next;
}
p->next=NULL;
cout<<"创建成功"<<endl;
}
else//如果输入0就建立空链表
{
head->next=NULL;
cout<<"创建一个带头结点的空链表完成"<<endl;
}
}
void counts(Node *p)//计算链表节点数2
{
int i=0;
p=p->next;
while(p!=NULL)
{
cout<<p->x<<endl;
p=p->next;
i++;
}
cout<<"一共有"<<i<<"个元素"<<endl;
}
Node * find(Node *p)//查找特定元素的前驱结点3
{
int x;
cout<<"输入要查找的元素"<<endl;
p=p->next;
Node *qq=p;//默认前驱为头结点
cin>>x;
while(p!=NULL)
{
if(p->x==x)//如果第一个元素就是刚返回头结点
return qq;
qq=p;//不是的话,记录这是结点,如果这个是的话,就返回这个结点
p=p->next;
}
return NULL;//没找到就返回空指针
}
void del(Node *p)//删除指定元素4
{
int x;
int num=0;
Node *temp=p;
cout<<"输入要删除的元素"<<endl;
cin>>x;
while(temp->next!=NULL)
{
while(temp!=NULL &&temp->next!=NULL&& temp->next->x==x)//循环相同元素
{
temp=temp->next->next;
num++;
}
if(temp!=NULL)
temp=temp->next;
}
if(num==0)
cout<<"删除失败,无可删除元素"<<endl;
else
cout<<"删除成功,共删除了"<<num<<"个元素"<<endl;
}
void rev(Node* &p)//反转链表,因为交换的是指针变量的值,要用引用类型才能达到目的
{
Node *p1,*p2,*p3;
p1 = p;
p2 = p->next;
while(p2 !=NULL)//通过交换指针的方法转化,使指针转向
{
p3 = p2->next;
p2->next = p1;
p1 = p2;
p2 = p3;
}
p->next->next = NULL;
Node *head=new Node;//重新加个头结点
head->next=p1;
p=head;
}
void DelMN(Node *p)//删除区间外的元素6
{
int max, mini;
cout<<"请输入区间"<<endl;
while(1)//区间的合法验证
{
cin>>mini>>max;
if(mini>max)
{
cout<<"输入非法,重新输入"<<endl;
}
else
break;
}
while(p!=NULL && p->next!=NULL)
{
while(p!=NULL && p->next!=NULL && p->next->x>max || p->next->x<mini)
{
p->next=p->next->next;
if(p->next==NULL)
break;
}
p=p->next;
}
}
void linksorts(Node *p)//链表元素排序,便与删除相同的元素
{
int temp;
bool flag=true;
Node *q=p->next;
while(flag)
{
flag=false;//标志,看是否元素进行了交换,如果,遍历了整个表没有交换,说明有序
while(q->next!=NULL)
{
if(q->x > q->next->x)//降序排列交换
{
temp=q->x;
q->x=q->next->x;
q->next->x=temp;
flag=true;
}
q=q->next;
}
q=p->next;
}
//play(p);
}
void DelOthers(Node *p)//与上面的排序配合来删除相同元素
{
linksorts(p);
int temp;
temp=-1111;//初始为一个特殊值
while(p!=NULL && p->next!=NULL)
{
while(p->next->x==temp)
{
p->next=p->next->next;
if(p==NULL || p->next==NULL)
break;
}
if(p!=NULL && p->next!=NULL)
temp=p->next->x;
p=p->next;
}
cout<<"删除成功"<<endl;
}
void divo(Node *p)//分成二个链表8
{
Node *headj =new Node;//奇数链表的头
Node *temps=headj;
Node *heado=new Node;//偶数表的头
Node *tempp=new Node;
tempp=heado;
Node *temp=p->next;
while(temp!=NULL)
{
if(temp->x%2!=0)//判断元素性质,并分别放入不同的表
{
temps->next=new Node;
temps->next->x=temp->x;
temps=temps->next;
}
else
{
tempp->next=new Node;
tempp->next->x=temp->x;
tempp=tempp->next;
}
temp=temp->next;
}
temps->next=NULL;//将表尾NULL
tempp->next=NULL;
cout<<"分开后的奇数链如下:"<<endl;//调用输出函数输出两个表
play(headj);
cout<<"分开后的偶数链如下:"<<endl;
play(heado);
}
int main()
{
Node *head=new Node;
head->next=NULL;
Node *p;
int n;
while(1)
{
cout<<" 第二次实验关于单链表的基本操作"<<endl;
cout<<"1.建立一个带头结点的单链表"<<endl;
cout<<"2.计算单链表的长度"<<endl;
cout<<"3.查找值为x的直接前驱结点q"<<endl;
cout<<"4.删除值为x的结点"<<endl;
cout<<"5.把单向链表中元素逆置"<<endl;
cout<<"6.删除m,n区间以外的元素"<<endl;
cout<<"7.删除值相同的元素"<<endl;
cout<<"8.将些链表分成两个奇偶链表"<<endl;
cout<<"9.结束退出"<<endl;
cout<<"请选择要执行的操作"<<endl;
cin>>n;
switch(n)
{
case 1: built(head);break;
case 2: counts(head);break;
case 3: p=find(head);if(p==NULL)cout<<"不存在"<<endl; break;
case 4: del(head); break;
case 5: rev(head);break;
case 6: DelMN(head);break;
case 7: DelOthers(head);break;
case 8: divo(head);break;
case 9: goto sub; break;//如果选退出,用goto跳出双重循环
}
}
sub:
return 0;
}
追问
谢谢您啦
热心网友
时间:2023-11-24 17:55
楼上已经有人给出代码了,我给稍微解释一下吧。一个链表,你可以看着是一串宝石,链表节点的数据就是宝石,可以是int的,可以是double的,就像宝石可以是红宝石,可以是蓝宝石,可以大,可以小。插入节点,也就是在这么一串宝石里面再插一个宝石进去,当然,要选好位置,这个位置就要靠指针来定位,指针就像是串着宝石的绳子一样,(假设你不知道这串宝石有多长),你只能顺着绳子往上找,这样才能找到你想要的位置。删除也是一样,顺着绳子找到你要删除的宝石,这就是指针的用法了。。。。希望能帮到你追问
谢谢你啦 帮忙看一下吧
追答一共就实现了三个功能,其实最好的方法是,你自己画一画,拿张纸,一个结果体是一个节点,节点里面有数据,有指针,自己画一画,看看具体过程就好了。。。。。这么给你讲实在是费力,而且讲不清。。。。。