C关于链表的那些事情
链表可是c的重头戏!!!为啥说他很重要,首先他包括的方面很重要,他包括了C的指针老大和结构体。想必指针的地位不用我来多说吧!!!指针因为太灵活了,所以可以使用的方面有很多,而链表则将他和结构体结合在一起,是更难了嘛!!!答案是错误的!!!
其实结构体就是一种数据的集合,将一些数据集合在一个群体里面,并没有很难理解的东西,而指针则是给每个结构体提供指向的,这样所形成的数据就成为一种链状的结构,所以称为链表!!!(下面我将一个链表解析下来,具体给大家讲述一下链表的具体形态)
//链表的创建区域(链表由指针和结构体组成)
struct student //此时该结构体就类似一个节点,节点包括姓名和年龄
{
char name[20];
int age;
student *next; //定义一个结构体指针指向下一个节点
};
在上面的程序是链表创建的第一步骤,首先你必须有个容器来容纳你的数据,而那个数据结构就是结构体!
其实数据啥的都不是重点,他只是暂时存在那个位置而已!关键是将他们链接在一起的指针,将每个数据集合串联起来看起来就像珠串一样,所以叫链表!
现在要进行数据的输入了,很简单跟结构体赋值一样,但是要将每个数据连接起来,因为他们是拴在一根绳子上的蚂蚱,这个要敲重点!!!
//数据的插入区域
student c={"xiaoyu",28,NULL}; //不能用[]这个符号
student b={"xiaozhu",27,&c}; //等会要将小猪删除
student a={"xiaoling",23,&b};
student *head=&a; //头指针,指向a
上面就是将数据一个个输入的,定义一个head指针直接指向a数据域,其实理解一下就是将a当作head了,head指向的也是有数据的,而不是一个空的头,然后一个个连接起来,记得最后的指向要置为空因为你没有位置给他了,所以只利用
NULL将他置空,让他不要乱跑!!!
既然数据已经都搞定了,我们现在要实现一个正常对链表的操作问题吧!
首先就是查找数据的问题:
//链表的查找功能
student *cpointer=head; //建立一个指针指向头节点
cout<<"查找姓名为xiaoyu的年龄:"<<endl;
while(cpointer) //遍历链表
{
if(strcmp(cpointer->name,"xiaoyu"))
{
cout<<"找到此人年龄为:"<<cpointer->age<<endl;
break; //跳出循环
}
cout<<cpointer->name<<","<<cpointer->age<<endl; //输出节点里面的信息
cpointer=cpointer->next; //指针指向下一个节点
}
if(cpointer==NULL)
{
cout<<"没有此人"<<endl;
}
既然它是利用链表将他一个链接起来,我们遍历他的时候肯定也需要一个可以移动的指针是吧!所以定义一个
student *cpointer=head; //定义一个学生结构体类型的指针cpointer指向他的头指针,然后一个个遍历数据
(这里补充要提一下strcmp函数,这个函数是用来比较两个字符或者字符串是否一样的,如果一样返回0如果不一样前面大的话返回正值,后面大的返回一个负值)但是如果没有找到这个人呢,我们肯定也要机器返回一个值来告诉我们结果,所以用了if条件语句判断是否查找到最后的一个值,如果是的话指针指向NULL则没有此人。
查找结束后,就需要增加数据了,增加数据的话你必须先创造一个数据出来,不能平白无故产生数据!!!
/*待插入的数据如下*/
student d={"xiaodong",27,NULL}; //为什么也给他赋一个空值呢,因为不知道他的位置在哪里暂时先放着
student d={"xiaodong",27,NULL}; //为什么也给他赋一个空值呢,因为不知道他的位置在哪里暂时先放着
就要先产生如上的一个数据,但是他的指向还是未知的,通过插入功能将数据插入。
//链表的插入功能(实现插入需要两个指针来执行操作)
student *before=head; //插入需要建立两个指针,可以都指向第一个位置
student *pointer=before->next; //第二个指针指向第一个数据域
while(before)//遍历链表
{
if(strcmp(before->name,"xiaozhu")==0) //strcmp函数的作用是比较两个字符串的大小,相同的话等于0
{
d.next=pointer; //第一步
before->next=&d;//第二步将d的首地址赋给before的下一个地址
break;
}
before=before->next; //两个指针都实现了移动
pointer=pointer->next; //都移动相同的距离
}
if(pointer==NULL)
{
cout<<"没有找到该学生无法插入!!!"<<endl;
}
//显示插入的结果,我要将数据插到xiaozhu后面。
pointer=head;
cout<<"将数据插入后的结果:"<<endl;
while(pointer)
{
cout<<pointer->name<<","<<pointer->age<<endl;
pointer=pointer->next;
}
切记,插入和删除都需要两个指针。而且断开要链表有个致命的点,不要将链表切断后再插入,因为一个链表本来就
是根据指针链接在一起的,如果强行先切断联系后这个链表后面的数据哪里去找地址存储呢,要将插入的数据先插到后一个数据的头位置,然后再断开,不然后面的数据全部缺少关联。(给你们画个图理解一下)
一定要有先后顺序哦!!!(图二那个×是切断的意思)
最后一共功能就是删除的功能!!!
//链表的删除功能(同样也需要两个指针来运行,单个指针不行,头节点不能删除掉,因为删除了就没了)
student *ibefore=head; //插入需要建立两个指针,可以都指向第一个位置
student *ipointer=ibefore->next;
while(ipointer)//遍历链表
{
if(strcmp(ipointer->name,"xiaoyu")==0)
{
ibefore->next=ipointer->next;
break;
}
ibefore=ipointer;
ipointer=ipointer->next;
}
if(ipointer==NULL)
{
cout<<"没有该数据无法删除!!!"<<endl;
}
同样的需要两个指针,没毛病!!!
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
贴一下全部的源码:
// 链表的初始学习.cpp : 定义控制台应用程序的入口点。
//
//利用链表创建三个学生的信息,学生信息包括信息和年龄
#include "stdafx.h"
#include<iostream>
using namespace std;
//链表的创建区域(链表由指针和结构体组成)
struct student //此时该结构体就类似一个节点,节点包括姓名和年龄
{
char name[20];
int age;
student *next; //定义一个结构体指针指向下一个节点
};
//链表的创建区域
int _tmain(int argc, _TCHAR* argv[])
{
//数据的插入区域
student c={"xiaoyu",28,NULL}; //不能用[]这个符号
student b={"xiaozhu",27,&c}; //等会要将小猪删除
student a={"xiaoling",23,&b};
student *head=&a; //头指针,指向a
/*待插入的数据如下*/
student d={"xiaodong",27,NULL}; //为什么也给他赋一个空值呢,因为不知道他的位置在哪里暂时先放着
//链表的查找功能
student *cpointer=head; //建立一个指针指向头节点
cout<<"查找姓名为xiaoyu的年龄:"<<endl;
while(cpointer) //遍历链表
{
if(strcmp(cpointer->name,"xiaoyu"))
{
cout<<"找到此人年龄为:"<<cpointer->age<<endl;
break; //跳出循环
}
cout<<cpointer->name<<","<<cpointer->age<<endl; //输出节点里面的信息
cpointer=cpointer->next; //指针指向下一个节点
}
if(cpointer==NULL)
{
cout<<"没有此人"<<endl;
}
//链表的插入功能(实现插入需要两个指针来执行操作)
student *before=head; //插入需要建立两个指针,可以都指向第一个位置
student *pointer=before->next; //第二个指针指向第一个数据域
while(before)//遍历链表
{
if(strcmp(before->name,"xiaozhu")==0) //strcmp函数的作用是比较两个字符串的大小,相同的话等于0
{
d.next=pointer; //第一步
before->next=&d;//第二步将d的首地址赋给before的下一个地址
break;
}
before=before->next; //两个指针都实现了移动
pointer=pointer->next; //都移动相同的距离
}
if(pointer==NULL)
{
cout<<"没有找到该学生无法插入!!!"<<endl;
}
//显示插入的结果,我要将数据插到小猪后面。
pointer=head;
cout<<"将数据插入后的结果:"<<endl;
while(pointer)
{
cout<<pointer->name<<","<<pointer->age<<endl;
pointer=pointer->next;
}
//链表的删除功能(同样也需要两个指针来运行,单个指针不行,头节点不能删除掉,因为删除了就没了)
student *ibefore=head; //插入需要建立两个指针,可以都指向第一个位置
student *ipointer=ibefore->next;
while(ipointer)//遍历链表
{
if(strcmp(ipointer->name,"xiaoyu")==0)
{
ibefore->next=ipointer->next;
break;
}
ibefore=ipointer;
ipointer=ipointer->next;
}
if(ipointer==NULL)
{
cout<<"没有该数据无法删除!!!"<<endl;
}
//删除成功结果显示,我将b给删除了。
pointer=head;
cout<<"将数据删除后的结果:"<<endl;
while(pointer)
{
cout<<pointer->name<<","<<pointer->age<<endl;
pointer=pointer->next;
}
//将链表中所有元素输出的功能,我将它注释掉了,不过原理很简单(没啥好说的)
/*pointer=head;
while(pointer)
{
cout<<pointer->name<<","<<pointer->age<<endl;
pointer=pointer->next;
}*/
return 0;
}
总结一下:链表就是这样的一个数据集合,没有其他的功能。数组其实有些的性质跟它也差不多,各有各的优点,关键看如何使用。
附(数组与链表关系图,各有各的优点嘛,关键要用的好)