真正有用的动态变量很少会是int,double这样的简单类型.相反都是一些复杂类型,比如数组,结构体,或类.结构体或类类型的动态变量通常由一个或多个成员变量,这些变量是指针,可将动态变量连接到其它动态变量.
一.节点
在C++中,节点作为结构或类实现.
struct ListNode
{
string item;
int count;
ListNode *link;
}
typedef ListNode* ListNodePtr;
C++支持箭头操作符: head->count=1; 替代了由圆点操作符和提领操作符组成的(*head).count=2;
C++11引入nullptr.避免因为NULL实际是数字0的造成歧义.
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void func(int *p)
{
cout<<"null"<<endl;
}
void func(int p)
{
cout<<0<<endl;
}
int main(int argc, char** argv)
{
//func(nullptr);
func(NULL);
return 0;
}
二.链表(节点列表)
1.在表头插入节点(头插法)
void headInsert(ListNodePtr& head,int c,string i)
{
ListNodePtr tempPtr;
tempPtr=new ListNode;//开辟新节点
tempPtr->count=c;
tempPtr->item=i;
tempPtr->link=head;
head=tempPtr;
}
2.遍历
while(head->link!=NULL)//普通遍历
{
cout<<head->item<<":"<<head->count<<endl;
head=head->link;
}
// for(iter=head;iter->link!=NULL;iter=iter->link)//迭代器遍历
// {
// cout<<iter->count<<endl;
// }
3.在链表中部插入节点
void insert(ListNodePtr afterMe,int c,string i)
{
ListNodePtr tempPtr;
tempPtr=new ListNode;//开辟新节点
tempPtr->count=c;
tempPtr->item=i;
tempPtr->link=afterMe->link;
afterMe->link=tempPtr;
}
4.删除节点
void del(ListNodePtr &head,int discardTarget)
{
ListNodePtr pb,pf;//搜索删除指针
pb=head;
if(head==NULL) cout<<"空链表"<<endl;//处理空列表
else{
while(pb->count!=discardTarget&&pb->link!=NULL)
{
pf=pb;
pb=pb->link;
}
if(pb->count==discardTarget)
{
if(pb == head)//找到的节点是头节点
{
head = pb->link;
}
else//找到的节点是普通节点
{
pf->link = pb->link;
}
free(pb);
}
else cout<<"未搜索到目标"<<endl;
}
}
5.搜索节点
ListNodePtr search(ListNodePtr head,int target)
{
ListNodePtr here=head;
if(here==NULL) return NULL;//处理空列表
else{
while(here->count!=target&&here->link!=NULL)
{
here=here->link;
}
if(here->count==target) return here;
else return NULL;
}
}
完整代码如下:
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
struct ListNode
{
string item;
int count;
ListNode *link;
};
typedef ListNode* ListNodePtr;
void headInsert(ListNodePtr& head,int c,string i)
{
ListNodePtr tempPtr;
tempPtr=new ListNode;//开辟新节点
tempPtr->count=c;
tempPtr->item=i;
tempPtr->link=head;
head=tempPtr;
}
void insert(ListNodePtr afterMe,int c,string i)
{
ListNodePtr tempPtr;
tempPtr=new ListNode;//开辟新节点
tempPtr->count=c;
tempPtr->item=i;
tempPtr->link=afterMe->link;
afterMe->link=tempPtr;
}
void del(ListNodePtr &head,int discardTarget)
{
ListNodePtr pb,pf;//搜索删除指针
pb=head;
if(head==NULL) cout<<"空链表"<<endl;//处理空列表
else{
while(pb->count!=discardTarget&&pb->link!=NULL)
{
pf=pb;
pb=pb->link;
}
if(pb->count==discardTarget)
{
if(pb == head)//找到的节点是头节点
{
head = pb->link;
}
else//找到的节点是普通节点
{
pf->link = pb->link;
}
free(pb);
}
else cout<<"未搜索到目标"<<endl;
}
}
ListNodePtr search(ListNodePtr head,int target)
{
ListNodePtr here=head;
if(here==NULL) return NULL;//处理空列表
else{
while(here->count!=target&&here->link!=NULL)
{
here=here->link;
}
if(here->count==target) return here;
else return NULL;
}
}
int main(int argc, char** argv)
{
ListNodePtr head;//头指针
ListNodePtr srhItem;//搜索指针
ListNodePtr iter;//迭代器指针
head=new ListNode;//开辟新节点
headInsert(head,200,"学习用品");
headInsert(head,300,"生活用品");
headInsert(head,400,"工作用品");
// insert(head->link->link,900,"总计");
//
// srhItem=search(head,300);
// cout<<"查找到该笔款项所对应的花费单元为:"<<srhItem->item<<endl;
del(head,100);
while(head->link!=NULL)//普通遍历
{
cout<<head->item<<":"<<head->count<<endl;
head=head->link;
}
// for(iter=head;iter->link!=NULL;iter=iter->link)//迭代器遍历
// {
// cout<<iter->count<<endl;
// }
return 0;
}
三.链表的变体
1.双链表
struct ListNode
{
int data;
ListNode *forwardLink;
ListNode *backLink;
};
2.二叉树
struct TreeNode
{
int data;
TreeNode *leftLink;
TreeNode *rightLink;
};
名为root的指针指向根节点(顶部节点).根节点的作用类似于普通链表的表头节点.跟随连接,可以到达树中的任何节点.
在分支结束的节点中,两个连接变量均设为空,这些节点称为叶节点.
二叉树能够高效存储和检索数据.
四.类构成的链表(Node类)
前面创建链表时,是用struct容纳节点内容,同样地数据结构还有类,基本原理一样.
Node类的接口文件
//头文件node.h,类构成的链表
namespace linkedlistofclasses
{
class Node
{
public:
Node();
Node(int value,Node *next);
...//之前写的crud方法
private:
int data;
Node *link;
}
typedef Node* Nodeptr;
};