C语言链表很不明白,求详细说一下,非常感谢
1 delete函数没有考虑如果head指向的节点就是要删除的节点的情况。如果删除的节点是dead,调用delete函数之后,后续所有操作都是错误的。因为把第一个节点删除之后应该让head指向下一个。
在遍历单向链表的时候,通常有两个指针,一个是当前节点(current_node),一个是前一个节点(previous_node)。当遍历开始时,他们应该都初始化为head。遍历期间让current_node = previous_node->next;
当我们删除的时候要判断要删除的节点是不是head,如果是删除完成后要重新给head赋值。代码:
Q* deletenode(Q* head, int data)
{
Q* current_node = head, *previous_node = head;
while(current_node != NULL)
{
if (current_node->score == data)
{
if (head == current_node) head = current_node->next;
previous_node->next = current_node->next;
free(current_node);
current_node = previous_node->next ;
continue;
}
previous_node = current_node;
current_node = current_node->next;
}
return head;
}
2 node函数没有问题,但是list函数感觉有问题,要创建n个节点,直接一个for循环就可以,没有必要判断是不是1个节点。list只要返回一个head指针就好,如果传进如的node节点数为0,直接返回NULL即可。
楼主第一个函数是一个数据存储的函数吧
先解释下3个指针变量的作用
*head:用于保存头文件的指针
*p:用于指向当前的下一个地址,只起到临时作用
*q:用于保存当前位置的地址
函数逻辑是用*head保存头指针,然后先移动*p,如果*p指向的是*head,说明这条链只有一个节点,就是头地址(头指针指向的地址),既然要继续,所以需要if(head->next==head)这句来判断是否*p指向的是头地址;如果不是*p指向的不是头地址,那么*p前移,然后*q也前移,*p一定要比*q先前移,所以*p在*q前面。
如果输入完毕了,及输入了回车号,结束输入,然后*q指向头*head。
那个print()函数是用来输出的,输出除了第一个元素以后的字母。
p=tail->next->next这句话就是p指向tail的下一个的下一个元素的地址,首先,p的初始值是上面的head头地址的内容,里面什么都没有,所以要一个next指向下一个,那么再下一个,就是第二个字母了,具体为什么要从第2个字母开始输出,就要问你了,不懂这个print()的目的。
哈哈,你的第一个函数返回的应该是q
既然百度上都有了我就说说我的理解
我觉得‘’链表‘’故名思义就是将一些东西连锁起来成一个串,或者环形的,想来想去如果这些东西一一对应那就只有线和环两种形态了
而这些东西就是数据,我理解就是一个个变量,或者书中所说的节点,链接他们的东西就是指针了
传说是约瑟夫提出这么一个问题编号为1,2, 。。。,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报到m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。
这里,选择使用链表来实现,具体的使用单链表中的循环链表来实现。
首先先说下链表的实现,
1>为了创建一个链表,首先先建一个节点结构:前面说到有变量和线索链接(定义成数据域和指针)
struct Node{
int Data;
Node *next;
};
节点的数据域存放计算的数据,节点的next指针域存放指向下一节点的地址
2>然后创建我们的链表类List类,在List类中我们要添加实现链表操作的方法,(这些就算是基本操作了)包括:
List();
void insertNode(int val);//插入到所给值得前面
void deleteNode(int val);
bool empty();
void outputNode();
还要添加一个私有成员, Node *head; 即头指针;
构造函数: 初始化head = NULL;
插入操作:
首先新建节点并初始化,
Node *s;
s = (Node*)new(Node);
s->Data = val;
进行一下判断:
(1).if(head==NULL)//头指针为空
(2).Node *p = head;
if(p->Data==val)//插入点为第一个节点
(3).Node *q;
while(p->Data != val)//循环寻找插入节点
(4).if(p->next == NULL)//插入节点是尾节点
删除操作:
首先建两个指针,Node *p,*q;判断:
(1).if(head == NULL)//链表为空
(2).p= head;
if(p->Data == val)//删除节点是第一个节点
(3).while((p->Data != val)&&(p->next != NULL))//循环寻找删除节点
(4).if(p->Data == val)找到节点
if(p->next == NULL)//节点不存在
判空操作:
这是一个可选的方法,return head == NULL;//判断链表是否为空
输出操作:
定义一个指针,Node *current;
初始化为 current = head;
循环输出 while(current->next != NULL)
以上就是一个能实现基本操作的链表类,这里只给出了算法,希望能够理解
3>下面说下约瑟夫算法的实现,使用循环链表
循环链表同单链表基本相似,只是循环链表尾节点的next指针始终指向链表的首地址,因此在插入删除操作时会有些不同的地方
节点结构同上,
为了实现约瑟夫算法
添加如下方法:
List();
void init(int val);//向链表中添加值
void deleteNode(int val);
bool empty();
void output();
void calculate();//计算约瑟夫算法
void setM(int val);
添加私用成员,Node *head;
int m;
int counter;//记录链表中的节点的个数
构造函数:
head= (Node*)new(Node);
counter = 0;
head->Data = counter;
head->next = NULL;
插入操作:
//这里为了具体实现约瑟夫算法,只是在链表的结尾添加数值
Node *s,*p;
s = (Node*)new(Node);
s->Data = val;
if(head->next == NULL)//首节点
head->next = s;
s->next = head->next;
counter++;
head->Data = counter;
else
p = head->next;
while(p->next != head->next)//找到链表尾节点
p = p->next;
p->next = s;
s->next = head->next;
counter++;
head->Data = counter;
删除操作:
//这里和单链表不太一样
Node *p,*q;
p=head->next;
if(head->next == NULL)//空链表
return;
if(p->next == head->next)//p是第一个节点,这时候要把尾节点的next指针指向第二个节点
q = p;
while(q->next != head->next)//找到尾节点
q = q->next;
head->next = p->next;
q->next = head->next;将新的头结点next域赋给尾节点的next域
delete p;
counter--;
head->Data = counter;
while(p->Data != val)//寻找节点
q = p;
p = p->next;
q->next = p->next;
delete p;
counter--;
head->Data = counter;
输出操作:
Node *current = head->next;
while(current->next != head->next)//输出节点
判空操作:
return head->Data == 0;
计算操作:
Node *temp;//用来存放循环的下一节点的指针
temp = head->next;
loop: Node *p;//这里使用的是goto语句,当然也可以用其他的方法:)
p = temp;
int count = 1;//计数器
while(count != m)
count++;
p= p->next;
m = p->Data;
temp = p->next;//保护现场:赋值,存放指针
deleteNode(p->Data);
if(!empty())//判空
output();
goto loop;
else
cout<<"FINISH!"<<endl;
setM(int val): m = val ;
这里想说的是,在删除循环链表的第一个节点的时候,不要忘了给尾节点的next指针赋一个新的值!
自己百度,要多详细有多详细。
C语言单链表部分,一直不懂划线部分什么意思,能不能详细解释一下_百度...
p=p->next \/\/p指向p的后继节点,即s
C语言链表很不明白,求详细说一下,非常感谢
\/\/这里和单链表不太一样 Node *p,*q; p=head->next; if(head->next == NULL)\/\/空链表 return; if(p->next == head->next)\/\/p是第一个节点,这时候要把尾节点的next指针指向第二个节点 q = p; while(q->next != head->next)\/\/找到尾节点 q = q->...
c语言的链表怎么理解
建议你看一下书。 追问: 啊?我C语言都没有学好,就去看C++? 回答: 呵呵,不是这个意思。刚才那个程序是C的。C++的STL中有自带的链表类,建议你以后学习。把握链表,核心是结点,结点核心就是数据+指针。多看几个例子,比如严蔚敏的数据结构,就写的很好。打字不易,如满意,望采纳。
c语言的一串链表看不懂啊
struct stud_node *Creat_Stud_Doc() \/\/应该是链表插入算法,名称上看该是学生信息用链表存储 {int num,score; \/\/定义学号和成绩变量 char name[20]; \/\/定义数组存放名字 int size=sizeof(struct stud_node); \/\/ size表示存放每个学生 节点的大小(字节数)struct stud_node *head,...
c语言,链表究竟有多难?老师没教这部分。想自己学,但不知道能不能学会...
链表在很多场合都用得上,比如做一个学生信息系统等等~链表如果理解好,还是不会太难的。前提需要对结构体和指针有一定的了解程度。可以先学习建立一个静态链表,然后建立一个动态的单链表,再然后双链表。总之需要一步一步慢慢来。
C语言 如图p->link 不懂?!不是已经有p=h->link了吗?
h是链表的头结点 p=h->link; 表示指针p指向头结点后面的结点 p=p->link; 表示指针p指向当前结点的下一个结点。
一口气玩转链表(C语言版)
节点与头结点链表中的每个元素被称为节点,包含数据域和指针域。头结点并非必需,但用于标识链表的起始位置。在C语言中,可以定义一个结构体来表示节点,如头结点的创建和使用。链表操作创建链表后,可以进行增删查改操作。向链表添加元素、删除指定元素、查找数据以及更新元素都有特定的步骤和实现代码,这些...
麻烦讲解一下C语言中的链表
一般链表在应用时,会额外建立一个链表头。在链表头里会有一些方便对链表操作的东西。比如你说的free指针,链表的第一节点地址,链表的尾地址,甚至一些控制变量如链表容量等 至于链表的具体应用很复杂,但其根本不会改变,并且链表的数据区可以是任何类型的数据,甚至可以是子链表。
C语言关于链表的问题
1,string 是关键词,你应该知道,怎么可以用它来命名结构体呢?2.你的链表很有问题,链表不是这样写的 ,对于链表,要在他的尾指针处加上NULL,这样可以防止内存泄漏,3,程序要分层,比如,你对你的链表,你都没有办法检测这个链构建的对不对,应该在结构体后面至少分成两个函数,一个负责链表的...
在C语言中,什么是链表呀?
程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。编辑本段特点 线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其...
资琳冠沙: NODE * fun(NODE *h) //NODE是节点结构体定义,函数应该是返转一个链表,也就是头节点变成尾,尾变成头 { NODE *p, *q, *r;p = h; //p指向传进来的节点h,应该是头节点if (p == NULL) //假如传进来的链表节点h为空,说明是空链表,没法反...
杭州市18447612963: 在C语言中,什么是链表呀? - ?
资琳冠沙: 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 相比于线性表顺序结构,操作复杂.由于不必须按顺序存储,...
杭州市18447612963: C语言 链表 如何理解? - ?
资琳冠沙: 满意答案飞狙仔16级2011-01-18别听那人忽悠你,想学数据结构并不需要链表的基础.当然,链表也很重要,以线性表为例:链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是...
杭州市18447612963: C语言链表很不明白,求详细说一下,非常感谢 - ?
资琳冠沙: 既然百度上都有了我就说说我的理解 我觉得''链表''故名思义就是将一些东西连锁起来成一个串,或者环形的,想来想去如果这些东西一一对应那就只有线和环两种形态了 而这些东西就是数据,我理解就是一个个变量,或者书中所说的节...
杭州市18447612963: 我是c语言的初学者(自学)学到链表是看不太懂了,现求简单一点的链表的入门知识 - ?
资琳冠沙: 同意wyjq395 干脆学c++吧,那就没链表的烦恼了 ,呵呵回答者:pawmhhh - 试用期 一级 12-9 00:26 你有没有学过C++啊,C++怎么会没有链表.无语...指针在链表里面只是最简单的应用,只是定义个指针,给指针赋个值而已.楼主看不懂最主要的可能是没有写过长一点的程序,接触数据结构后觉得那程序长了,有点怕.其实关键是要多写,多练.可以加QQ群30703663.数据结构的问题保证可以得到解决.
杭州市18447612963: C语言链表看不懂 - ?
资琳冠沙: 这个开始学的时候主要是画图,里面的精华就是要知道前一个结点的指针域指向下一个结点的数据域,通常方法是先建立一个头结点(注意要给它分配空间,这是初学者最容易犯错的),再一次新键一个结点加上去,但是不要让指针变为野指针了(就是要让指针指向一个具体的内存),建议看一下c语言程序设计那本书,后面有样本~~
杭州市18447612963: 有谁来详细讲解下C语言链表 - ?
资琳冠沙: 这个并不是一句两句可以说清的,给举个例子吧,链表就像火车,有很多个车厢,车厢之间有一根线连着,而火车头就像链表的头,每个车厢就想链表节点,而至于那个线,就是链表节点之间的指针连接.(PS:当然链表有很多分类,什么单向链表,循环链表,双向链表等,但都大同小异,只要搞清楚单向链表,其他的自然都不难理解)
杭州市18447612963: C语言的链表到底是个什么东西?我看书感觉看不懂 求人帮解释一下 感激不尽 老师说写电话本的删除功能要用 - ?
资琳冠沙: 链表是体现了c语言介于高级语言和低级语言中间的一种,链表能大概对内存进行操作,这样的操作汇编级别的才有的,许多高级语言都封装了的.关于删除功能只能是可能会用到的,因为删除功能同样可以用数组解决,只是效率低了点就是了的.链表是c语言的精华,忘楼主勉之
杭州市18447612963: 计算机c语言中什么是链表?
资琳冠沙: 简单来说就是“承上启下”,区别于正常数组,存储的时候不是一连串连续的内存地址. 链表的特点在于结点,struct stu{ int num; int score; struct stu *next; } 这就是一个简单的链表, 上边两个是数据域,最后一个是指针域 指针域交代了下一个数据是存在哪里的, 这样计算机就可以直接去找到了. 这样便于插入和删除,缺点就是同等的空间下,链表存的数据少,因为他多了指针域.
杭州市18447612963: C语言的链表如何理解? - ?
资琳冠沙: 新手吧~ 大概是你用自然语言的理解方式来理解赋值了.=号在编程过程中表示的是赋值,也就是说,你写p=q的时候,就把q的值给了p,而p和q都是指针时,这句话的意思就变成了:p指向的地址变成了q指向的地址.也就是说,比如本来你的纸上有一个q指向后面的箭头,p也有一个,现在你做的工作就是把p的那个箭头擦掉,把p的箭头指向q的箭头指向的那个位置.再试试,如果还是不明白,继续追问~