Linked List part2 : List class

在linked list part2中, 我们定义了一个node class 如下:

有了这个node class之后, 我们可以利用这个class宣告很多的node class 的object:

然而虽然我们可以宣告很多的Contact类型的对象, 但是我们并没有将他们linke 起来组成一个linked list.。

为了实现这样的一个linked list, 我们需要宣告一个List class, 该class 具有一个指向节点类型Contact的对象的head指针变量。 最开始, 我们的head可能设置0, 也就是说我们的linked list 是empty。 一个linked list 可能有很多的operations, 例如判断其是否为空链表, 删除链表的某一个节点, 创建新的某个节点, 或者遍历链表等等。. 为了简便起见, 我们忽略其他的operations(亦methods, 也被称为成员函数)。

 

 

 

 

链表的节点添加可以从链表头向后添加(forward), 也可由从链表尾部(backWard)从后向前创建。

在这里我们介绍building linked list backward。

下面实现:

创建NewLinkedList工程中:

(1)Contact.h

/*
 * Contact.h
 *
 * Created on: Jul 6, 2014
 *    Author: ***
 *
 *
 */


 #ifndef CONTACT_H
 #define CONTACT_H

 #include <iostream>
 #include <string>

 class Contact {
    friend std::ostream& operator<<(std::ostream& os, const Contact& c);
    friend class ContactList;
    public: //public area
       Contact(std::string n = "none"); // constructor with default parameter


    private: //private area
       //you can add information like email address, phone number etc.
       std::string name;
       Contact* next;//linked pointer so it can be linked to the next node in the linked list
 };


 #endif // end of CONTACT_H


注意上面, 我们宣告了class ContactList 为类别Contact的友元类别。 也就说, ContactList的所有的成员函数就是类别Contact的友元函数。

所有所有ContactList 的成员函数都可以直接存取Contact的私有成员变量。

 

(2)Contact.cpp

/*
 * Contact.cpp, implementation file of Contact.h
 *
 * Created on: Jul 6, 2014
 *    Author: ***
 *
 *
 */

#include "Contact.h"

using namespace std;



Contact::Contact(string n):name(n), next(NULL) {

}

// overloading insertion operator
//return ostream reference so that we can chaining "<<"
//the argument is a constant reference of type Contact

ostream& operator<<(ostream& os, const Contact& c) {
   return os << "Name: " << c.name;
}


(3)类别ContactList的头文件:

/*
 *ContactList.h
 *
 *   created on Jul 6, 2014
 *      Author: ***
 *
 *
 */

 #ifndef CONTACT_LIST_H
 #define CONTACT_LIST_H


 #include "Contact.h" // the first thing to do is to include the node header file

 class ContactList {
     public:
        ContactList(); // prototype for constructor
        void AddToHead(const std::string&);//reference, 避免复制, 更快, const, 所以不让修改


     private:
        Contact* head;
        int length;
};

 #endif /*end of CONTACT_LIST_H*/


(3)ContactList.cpp

// an implementation of ContactList.h

#include "ContactList.h"
using namespace std;

ContactList::ContactList():head(0), length(0) {

}

void ContactList::AddToHead(const string& name) {
   Contact* newOne = new Contact(name);
   if(head == 0) {
      head = newOne;
   }
   else {
      newOne -> next = head;
      head = newOne;
   }
   length++;
}

在这里, 需要注意的是我们采用了动态内存分配的方法去创建从后向前我我们的linked list 添加新的节点。

即使函数调用结束, 由于是动态分配的内存, 所以不会dellocate。 但是调用函数结束后, 我们创建的节点的位置存储在newOne中, 而这个指针在函数内部声明的,所以位于stact中。 会随着函数调用的结束而被释放掉。 每次调用时 , 为这个指针重新分配内存。  也就是说创建的linked list 会保持新的程度, 实现我们的目的。

添加节点的时候。 else 里面的两个语句的顺序很重要。 不能改变顺序。 下面以几幅图说明。

最开始, 我们的指针head 指向null, 此时是空链表:

 

后来, 我们调用函数AddToHead("Bob"), 执行到new Contact(name)时, 如下情况:

 

执行语句(head == 0): head = newOne;

表达如下图:

 

 

 

当函数调用结束的时候, newOne由于在stack中, 所以内存会释放掉, 最终如下图:

 

 

当再次, 当我们再次调用函数AddToHead("Sally"), 执行到new Contact(name)时候, 情况如下:

 

由于此时head !=0, 所以会选择执行:

newOne -> next = head; head = newOne; 具体如下(两个语句先后对应下面两幅图):

 

 

 

当函数调用结束后, newOne 被释放掉:

 

 

 

注意上面的else内部的两个语句的先后顺序很重要, 要调换顺序, 会导致后面的节点丢失, 造成许多内存的浪费, 是错误的。

 

 

下面编写一个用于测试的application 文件:

//NewContactListApp

#include "ContactList.h"
using namespace std;

int main() {
   ContactList* cl1 = new ContactList;
   string name;
   while(true) {
      cout << "Enter the name of the contact, or q to quit:";
      cin >> name;
      if(name == "q")
         break;
      cl1->AddToHead(name);
   }
   return 0;
}


debug 查看内存个变量的变化情况。

 

 

NOTE:

CodeBlocks,cannot open output file permission denied的解决办法

在用CodeBlocks环境,mingw32编译器时经常遇到这个问题,一直的原因有两个:1.有正在run的exe文件。只要把它终结就好。2.目录名字中有空格或汉字。只要改成全英文就行了。

 

在这里, 我的exe被360 后的住了, 换个文件位置, 重新编译就好, 虽然运行完程序后, 360仍然会将其当做木马hold 住。 在google搜索问题根源, 得到如下答案:

If you think the executable is locked by a process, try Process Explorer from SysInternals. In the File/handle, enter Fibonacci.exe and you should see who holds the file.

If it is not enough, you can use Process Monitor (from SysInternals, again) to follow the activity of all processes on your system on Fibonacci.exe. With a little bit of analysis (call stacks), you'll may find out why the access to the file is denied and what make it disappear.

 

 

 

 

 

 

 

 

 


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值