作业二 双向链表
首先我们来看双向链表的定义 :
typedef int ElemType; typedef struct Node * PtrToNode; typedef PtrToNode Position; struct DListNode; typedef DListNode * DList; typedef struct Node { ElemType data; /*数据域*/ PtrToNode previous; /*指向前驱*/ PtrToNode next; /*指向后继*/ }Node; struct DListNode { PtrToNode head; /*指向头节点*/ PtrToNode tail; /*指向尾节点*/ int size; //链表中数据项数 }
示意图大概是这样的
DListNode是什么呢?相当于一个指路牌,让你可以直接走向头结点或尾节点。
双向链表要注意的是,如果只有一个节点 A,那么A既是头结点,也是尾节点。
所以我们在写插入删除操作的时候要进行分类讨论。
2264,插入 I
void InsertAtHead(DList L, ElemType x) { Position p = (PtrToNode)malloc(sizeof(Node)); p->data = x; if (L->head == NULL) { L->head = p; L->tail = p; p->next = NULL; p->previous = NULL; } else { p->next = L->head; L->head->previous = p; L->head = p; p->previous = NULL; } L->size++; }
//链表链接的时候基本准则都是 先连接再断开 ,虽然两个指针操作有点麻烦,但是还是比较好理解的
2265 插入2
void InsertAtTail(DList L, ElemType x) { Position p = (PtrToNode)malloc(sizeof(Node)); p->data = x; if (L->tail == NULL) { L->head = p; L->tail = p; p->next = NULL; p->previous = NULL; } else { p->previous = L->tail; L->tail->next = p; L->tail = p; p->next = NULL; } L->size++; }
2271,删除 I
void DelFirst(DList L, ElemType *e) { Position p = L->head; if (L->size == 0) return; if (L->tail == p) { L->head = NULL; L->tail = NULL; } else { L->head = p->next; p->next->previous = NULL; p->next = NULL; } *e = p->data; free(p); L->size--; }
2272 删除 II
void DelLast(DList L, ElemType *e) { Position p = L->tail; if (L->size == 0) return; if (L->head == p) { L->head = NULL; L->tail = NULL; } else { L->tail = p->previous; p->previous->next = NULL; p->previous = NULL; } *e = p->data; free(p); L->size--; }
链表清空(非销毁的时候)要把每项数字清零,并改正size的值(head、tail指向空别忘了)
2275 双向链表的清空
void ClearList(DList L) { Position p = L->head; while (p != L->tail) { p->data = 0; p = p->next; } L->size = 0; L->head = NULL; L->tail = NULL; }
其他的插入删除思路可以参考上面,剩下的比较简单就不说了