链表ALDS1-3-C:Doubly Linked List

来源:互联网 发布:hp g3110扫描仪软件 编辑:程序博客网 时间:2024/05/16 23:44

         如图4.8所示,表中的各元素称作“结点”。双向链表的结点是结构体,由数据本体(这里是整数key)、指向前一元素的指针prev以及指向后一元素的指针next组成。这些结构体通过指针连接成一个链,就形成了双向链表。


program4.3 C++双向链表的结点

strcut Node {
   int key;
   Node *prev, *next; 
};

        另外,在表头设置一个特殊的结点可以简化链表的实现。我们将这个结点称为“头结点”。头结点中虽然不包含实际数据,但他可以让我们更轻松的对链表做更改。比如加入头结点之后,我们将更容易实现删除元素的操作。



      init函数用于初始化链表。如图4.9所示,它会生成一个NIL结点作为链表的头结点,然后让prev和next都指向这个结点,从而创造一个空表。

program4.4 初始化双向链表

Node *nil;void init() {nil = (Node *)malloc(sizeof(Node));nil->next = nil;nil->prev = nil;} 
        头结点是添加元素的起点。这里的malloc是C语言标准库中的函数,用于动态申请指定大小的空间。另外,“->”是通过指针变量访问成员的运算符,称为箭头运算符。




        insert函数用于生成包含所输入键值的结点,并将该结点添加到标的开头。如图4.10所示这个函数会以头结点为起点分四步改变指针所指的方向。


program4.5 往双向表中插入元素

void insert(int key) {Node *x = (Node *)malloc(sizeof(Node));x->key = key;//在头结点后添加元素x->next = nil->next;nil->next->prev = x;nil->next = x;x->prev = nil; } 




      listSearch函数用于搜索元素,它可以在链表中寻找包含指定键值的结点,并返回其指针。假设cur为指向当前位置结点的指针,只要从头结点的next所指的结点,即链表开头的元素开始逐个执行cur = cur -> next,即可逐一访问每个结点。

program4.6 在双向链表中搜索元素

Node* listSearch(int key) {Node *cur = nil->next;  //从头结点后面的元素开始访问while( cur != nil && cur->key != key) {cur = cur->next;} retrun cur;}

        在访问过程中发现key或者指针回到头结点NIL时结束搜索,并返回此时cur的值。




        deleteNode函数会通过如图4.11所示的步骤改变指针所指的位置,从而删除指定的结点t。在C++中,我们必须手动释放已删除结点的内存。这里的free时C语言标准库中的函数,用于释放已不需要的内存空间。


program4.7 从双向链表中删除元素

void deleteNode(Node *t) {if( t == nil )  return;t->prev->next = t->next;t->next->prev = t->prev;free(t);}void deleteFirst() {deleteNode( nil->next );}void deleteLast() {deleteNode( nil->prev );}void deleteKey(int key)  {//删除已搜索到的结点deleteNode( listSearch(key)); }




例题;


代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>using namespace std;struct Node  {int key;Node *next,*prev;};Node *nil;void init()  {      //初始化 nil = (Node *)malloc(sizeof(Node));nil->next = nil;nil->prev = nil;}Node* listSearch(int key)  {    //找出含有键值key的结点     Node *cur = nil->next;    while( cur != nil && cur->key != key)  {    cur = cur->next;}return cur;}void insert(int key)  {       //在头节点后插入某个元素 Node *x = (Node *)malloc(sizeof(Node));x->key = key;x->next = nil->next;nil->next->prev = x;nil->next = x;x->prev = nil;}void deleteNode(Node *t)  {     //删除结点 被下面调用函数  调用 if( t == nil)  return;t->prev->next = t->next;t->next->prev = t->prev;free(t);  //释放已经不需要的内存空间 }void deleteFirst()  {    //删除头结点next所指向的结点 deleteNode(nil->next);}void deleteLast()  {    //删除头结点prev所指向的结点 deleteNode(nil->prev);}void deleteKey(int key) {deleteNode(listSearch(key));  //删掉搜索到的结点 }void printList()  {      //打印链表 Node *cur = nil->next;int isf = 0;while(1)  {if( cur == nil ) break;if(isf++ > 0) printf(" ");printf("%d",cur->key);cur = cur->next;}printf("\n");} int main(){int n,key,i;char com[20];cin>>n;init();int size = 0,np = 0,nd = 0;for( i=0; i<n; i++ )  {scanf("%s%d",com,&key);if( com[0] == 'i')  {  insert(key);  np++;  size++;} else if( com[0] == 'd')  {if( strlen(com) > 6)  {if( com[6] == 'F')  deleteFirst();else if( com[6] == 'L')  deleteLast();}  else  {deleteKey(key);  nd++;}size--;}}printList();return 0;}/*7insert 5 insert 2insert 3insert 1delete 3insert 6delete 5*/





原创粉丝点击