//////////////////////////////////////////// /* 1 什么是链表 数组就象容器,它的大小是不可调节的,这一点很令人头疼,因为假如你买了一个很大的容器,却用来盛比较少的东西的话,你会感到很浪费,但是如果你换成小容器的话,它双放不下许多的东西。 链表的出现无表中银决了这个问题,它将一个容器分解成若干个小容器,每一个小容器放入合适大小的元素,然后根据需要将它们链接起来 这些若干个小容器我们把它叫做节点,通常它们都按照顺序排列,排列在第一位的那个容器我们叫它头节点,最后一位的叫尾节点,由于它们的外形是那么的相似,所以假如你要找到放置在某个容器中的东西的话,你只有一个办法,那就是从第一个容易器开始往后找。 因为每个容器里除了放你要放置的东西外,还会放置下一个容器的地址,我们可以根据这个地址依次找到所需的容器 但是这里又有一个问题,那就是由于这些容器放了一些比较私人的东西,我不想叫人知道,所以把它们都分别放在比较隐蔽的地方,隐蔽的连我都不知道放哪些里去了,不过好在我还留了一个叫head的纸条, 下面写着第一个容器的位置,这样事情就容易多了,我根据这个head标签找到了第一个容器,打开一看,里面的东西不是我们想要到,失望之余,我又根据该容器里放置的next纸条(该纸条记录的是下一个容器的地址)找到了第二个容器 然后这么依次进行,直到找到我需要的东西为止 我们来操作一下: 为了便宜于理解,我们用结构体来代替类操作,这里先来说一下结构体,在C++中,结构体与类相同,不同的结构体的成员默认为公有成员,而类的成员默认为私有成员 */ ///////////////////////////////// //2.1 结构体链表 /* 我们来操作一下: 为了便于理解,我们用结构体来代替类操作,这里先来说一下结构体,在C++中,结构体与类相同,不同的是结构体的成员默认为公有成员,而类的成员默认为私有成员 既然它们相同,为什么又要两个关键字来做一样的事情呢?这是因为C语言时代的结构体,没有类方法,功能很单一,不能进行数据的封装和成员的继承,因此C++的创始人Bjame Stroustrup创造了高级 的结构体,也就是类 这里我们之所以用一来说明链表,就是因为结构体比较浅显易懂,我们理解了结构体的链表之后,再看类的链表就不那么抽象和晦涩了 */ /* #include <iostream> using namespace std; struct book //定义结构体 { int num; //图书编号 float price;//图书价格 struct book *next; //定义一个指针 //struct是类型,bookstruct类型的结构 }; int main() { book x, y, z, *head, *p; x.num = 10000; x.price = 14.6; y.num = 10004; y.price = 19.5; z.num = 1568; z.price = 186.2; //设置头节点 head = &x; //指x的地址赋值给head做为头节点指针 //head->next = &y; //第二个节点的内容为y x.next = &y; //这样才是正确的 y.next = &z; //第三个节点 z.next = NULL; //将最后一个节点的下一个节点设置为空就行了 p = head; while(p != NULL) { cout<<"num:"<<p->num<<endl; p = p->next; } return 0; }*/ // 3 静态链表 //本节两侧程序中所有结点的数据在内存中的分布都是在编译时就确定好了的,不会在运行时再进行动态地分配空间,比如说我们不能在程序运行时动态地对各个结点进行创建 //添加和删除的工作,这都是在运行前都已经确立好了的,我们只能在编译指向结点的指针,这种链表叫"静态链表" /* #include <iostream> using namespace std; class book //定义结构体 { public: int num; //图书编号 float price;//图书价格 book *next; //定义一个指针 //struct是类型,bookstruct类型的结构 }; int main() { book x, y, z, *head, *p; x.num = 10000; x.price = 14.6; y.num = 10004; y.price = 19.5; z.num = 1568; z.price = 186.2; //设置头节点 head = &x; //指x的地址赋值给head做为头节点指针 //head->next = &y; //第二个节点的内容为y x.next = &y; //这样才是正确的 y.next = &z; //第三个节点 z.next = NULL; //将最后一个节点的下一个节点设置为空就行了 p = head; while(p != NULL) { cout<<"num:"<<p->num<<endl; p = p->next; } return 0; }*/ // 4 动态链表 //链表结构也可能是动态的分配在顾念的,即在需要时才开辟结点的顾念空间,实现动态链接 //或者说当程序运行起来的时候,假设这个程序是图书管理程序,某个用户点击了创建新书,这时才会创建一个新书结点,而用户单击删除图书的时候,才会删除某个图书结点,这就是动态的创建和删除,那么人们如何实现动态的创建和删除结点呢? //在C语言中用malloc函数来开辟,用free来释放 /* #include <iostream> using namespace std; struct book //定义结构体 { int num; //图书编号 float price;//图书价格 struct book *next; //定义一个指针 //struct是类型,bookstruct类型的结构 }; int main() { //malloc 创建一个节点 void *p = malloc(sizeof(book)); //创建一个能放book大小的空间 free(p); //free将会删除p所指向的空间 //以上说的是在C语言中 //以C++中是用 new 来创建空间,delete 来删除指定空间 return 0; } */ // 5 动态链表的建立 /* #include <iostream> using namespace std; class book //定义结构体 { public: int num; //图书编号 float price;//图书价格 book *next; //定义一个指针 }; book *head = NULL; //定义一个head指针 book *crate() { book *p1, *p2; p1 = new book; head = p1; p2 = p1; //现在三个指针都指向同一个地址 cout<<"请输入图书的编号,以0结束"<<endl; cin>>p1->num; if(p1->num != 0){ cout<<"请输入图书的价格"<<endl; cin>>p1->price; }else{ delete p1; //删除指针 p2 = NULL; //把第二个指针清空 p2->next = NULL; //第二个针的下一个指针设置为空 head = NULL; //清空头指针 return head; } while(p1->num != 0) { p2 = p1; p1 = new book; cout<<"请输入图书的编号,以0结束"<<endl; cin>>p1->num; if(p1->num != 0){ cout<<"请输入图书的价格"<<endl; cin>>p1->price; } p2->next = p1; } delete p1; p2->next = NULL; return head; }; int main() { crate(); return 0; }*/ /* #include <iostream> using namespace std; class book //定认一个结构体 { public: int num; //图书编号 float price; //价格 book *next; //图书的下一个本图书的地址 }; //首先定义一个头指针 book *head; book *create() { //我们选建一个新的节点 book *p1, *p2; //p1做为下一个节点的指针,p2做为结构本的指针 p1 = new book; p2 = p1; head = p2; cout<<"请输入图书的编号,退出请输入0"<<endl; cin>>p1->num; if(p1->num != 0) { cout<<"请输入图书的价格:"<<endl; cin>>p1->price; }else{ //如果是退出的话 delete p1; p2 = NULL; p2->next = NULL; head = NULL; return head; } //cout<<"num:"<<head->num<<endl; //cout<<"price:"<<head->price<<endl; //如果不为0那么就循环让用户输入图书信息 while(p1->num != 0) { p2 = p1; //p1做为当前输入的指针,p2为结构本指针 //重新构造一个新的p1指针,如果这里不重新构造的话,那么这里一直就是在操作head跟p1 p2指针的同一个地址 //这里刚才少写了一句 p1 = new book; cout<<"请输入图书的编号,退出请输入0"<<endl; cin>>p1->num; if(p1->num != 0) { cout<<"请输入图书的价格:"<<endl; cin>>p1->price; } p2->next = p1; //cout<<"num:"<<head->num<<endl; //cout<<"price:"<<head->price<<endl; } //这里还多少一个中间的转换节点p1,我们在这里删除 delete p1; p2->next = NULL; return head; } int main() { book *s = create(); //cout<<"s:"<<s<<endl; //cout<<"main s:"<<s->num<<endl; //cout<<"main s:"<<s->price<<endl; //我这里来读取一下*p这个链表的信息 while(s) { cout<<"图书的编号是:"<<s->num<<", 图书的价格是:"<<s->price<<endl; if(s->next == NULL){ s = NULL; }else{ s = s->next; } } return 0; }*/