数据的存储结构有两种,一种是顺序存储,如数组。一种是链式存储,如链表。
链表(Link List)一般是通过结构体指针链接结构体变量,每一个结构体变量(相当于链条中的每个环节)称为链表的结点(Node)。
顺序存储中元素的内存单元是挨在一起的(可以通过下标访问和操作元素)。链式存储的元素的可以不挨在一起,相互之间通过一个额外的指针连接起来(通过节点指针来访问和操作节点)。
链表实现的注意事项:
1 一个链表始终需要一个头结点、一个尾结点;
2 结点总是动态分配的,每分配好一个结点会返回一个指针,需要嵌入到链表中,改变前后节点的指针指向。
实例代码:
运行:
附代码:
#include <iostream> using namespace std; struct node //定义结点结构类型 { char data; //用于存放字符数据 node *next; //用于指向下一个结点(后继结点) }; // …………创建………… node * Create() { node *head=NULL; //表头指针,一开始没有任何结点,所以为NULL node *pEnd=head; //表尾指针,一开始没有任何结点,所以指向表头 node *pS; //创建新结点时使用的指针 char temp ; //用于存放从键盘输入的字符 cout<<"请输入字符串,以#结尾:" <<endl; do //循环至少运行一次 { cin>>temp; if (temp!='#') //如果输入的字符不是#,则建立新结点 { pS=new node; //创建新结点 pS->data=temp; //新结点的数据为temp pS->next=NULL; //新结点将成为表尾,所以next为NULL if (head==NULL) //如果链表还没有任何结点存在 { head=pS; //则表头指针指向这个新结点 } else //否则 { pEnd->next=pS; //把这个新结点连接在表尾 } pEnd=pS; //这个新结点成为了新的表尾 } }while (temp!='#'); //一旦输入了#,则跳出循环 return head; //返回表头指针 } //…………遍历………… void Showlist(node *head) { node *pRead=head; //访问指针一开始指向表头 cout<<"链表中的数据为:" <<endl; while (pRead!=NULL) //当访问指针存在时(即没有达到表尾之后) { cout<<pRead->data; //输出当前访问结点的数据 pRead=pRead->next; //访问指针向后移动(指针偏移) } cout<<endl; } //…………查找………… node * Search(node *head,char keyWord) //返回结点的指针 { node *pRead=head; while (pRead!=NULL) //采用与遍历类似的方法,当访问指针没有到达表尾之后 { if (pRead->data==keyWord) //如果当前结点的数据和查找的数据相符 { return pRead; //则返回当前结点的指针 } pRead=pRead->next; //数据不匹配,pRead指针向后移动,准备查找下一个结点 } return NULL; //所有的结点都不匹配,返回NULL } // …………插入………… void Insert(node * &head,char keyWord,char newdata) //keyWord是查找的字符(确定插入的位置) { node *newnode=new node; //新建结点 newnode->data=newdata; //newdata是新结点的数据 node *pGuard=Search(head,keyWord); //pGuard是插入位置前的结点指针 if (head==NULL || pGuard==NULL) //如果链表没有结点或找不到关键字结点 { //则插入表头位置 newnode->next=head; //先连 head=newnode; //后断 } else //否则 { //插入在pGuard之后 newnode->next=pGuard->next; //先连 pGuard->next=newnode; //后断 } } // …………节点删除………… void Delete(node * &head,char keyWord) //可能要操作表头指针,所以head是引用 { if (head!=NULL) //如果链表没有结点,就直接输出提示 { node *p; node *pGuard=head; //初始化pGuard指针 if (head->data==keyWord) //如果头结点数据符合关键字 { p=head; //头结点是待删除结点 head=head->next; //先连 delete p; //后断 cout<<"被删除的结点是" <<keyWord<<endl; return; //结束函数运行 } else //否则 { while (pGuard->next!=NULL) //当pGuard没有达到表尾 { if (pGuard->next->data==keyWord) //如果pGuard后继结点数据符合关键字 { p=pGuard->next; //pGuard后继结点是待删除结点 pGuard->next=p->next; //先连 delete p; //后断 cout<<"被删除的结点是" <<keyWord<<endl; return; //结束函数运行 } pGuard=pGuard->next; //pGuard指针向后移动 } } } cout<<"The keyword node is not found or the link list is empty!" <<endl; } // …………链表删除………… void Destroy(node * &head) { node *p; while (head!=NULL) //当还有头结点存在时 { p=head; //头结点是待删除结点 head=head->next; //先连 delete p; //后断 } cout<<"The link list has been deleted!" <<endl; } // …………主函数………… int main() { node *head=NULL; head=Create(); Showlist(head); cout<<"在a的位置插入o:"<<endl; Insert(head,'a','o'); Showlist(head); cout<<"插除内容是m的节点:"<<endl; Delete(head,'m'); Showlist(head); Destroy(head); Showlist(head); cin.get(); cin.get(); return 0; } -End-