设计双向链表
要求
题目要我们实现有关双向链表的基本操作,即以下几个函数(与设计单链表相比,由于多了一个指向前一个节点的指针,因此链接两节点的操作要更加复杂,读者可以通过画图进行理解,事半功倍):
MyLinkedList* myLinkedListCreate() //创建双向链表 int myLinkedListGet(MyLinkedList* obj, int index) //得到下标为index的节点的值,如果index无效则返回-1 void myLinkedListAddAtHead(MyLinkedList* obj, int val) //链表头插 void myLinkedListAddAtTail(MyLinkedList* obj, int val) //链表尾插 void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) //在下标index处插入值为val的节点,如果index等于链表长度,则相当于尾插 void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) //删除下标为index的节点,如果index无效,则不操作 void myLinkedListFree(MyLinkedList* obj) //销毁链表
解析函数形参
同昨天的题目一样,设计单链表,题目所给函数传递的是一级指针,因此我们就要使用带哨兵位的双向链表
实现代码
typedef struct List { struct List *next; struct List *prev; int val; } MyLinkedList; //创建双向链表 MyLinkedList* myLinkedListCreate() { MyLinkedList *obj = (MyLinkedList *)malloc(sizeof(MyLinkedList)); obj->prev = obj->next = NULL; //令哨兵位的prev和next指针都初始化为空 return obj; } //返回下标为index的节点的数据,若index无效,则返回-1 int myLinkedListGet(MyLinkedList* obj, int index) { int count = 0; MyLinkedList *cur = obj->next; //obj不存储有效数据,因此从next开始计数 while(cur) { if(count == index) return cur->val; cur = cur->next; count++; } return -1; } //头插 void myLinkedListAddAtHead(MyLinkedList* obj, int val) { //创建新节点 MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList)); newHead->val = val; //如果链表为空 if(obj->next == NULL) { //直接将新节点接到哨兵位obj后 obj->next = newHead; newHead->next = NULL; newHead->prev = obj; } //如果链表不为空 else { //将新节点嵌入obj和第一个节点之间 obj->next->prev = newHead; newHead->next = obj->next; newHead->prev = obj; obj->next = newHead; } } //尾插 void myLinkedListAddAtTail(MyLinkedList* obj, int val) { //创建新节点 MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList)); newHead->val = val; //找到链表的尾 MyLinkedList *cur = obj; while(cur->next) cur = cur->next; //使新节点成为链表的尾 newHead->prev = cur; cur->next = newHead; newHead->next = NULL; } //在下标为index插入节点 void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) { //如果index为0,直接头插 if(index == 0) { myLinkedListAddAtHead(obj,val); return; } //创建新节点 MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList)); newHead->val = val; MyLinkedList *cur = obj->next; //obj不存储有效数据,因此从next开始计数 int count = 0; while(cur) { if(count == index) { //实现插入 cur->prev->next = newHead; newHead->prev = cur->prev; newHead->next = cur; cur->prev = newHead; } cur = cur->next; count++; } //如果index等于链表长度,则直接尾插 if(count == index && cur == NULL) { myLinkedListAddAtTail(obj,val); return; } } //删除下标为index的节点,若index无效,则不操作 void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) { int count = 0; MyLinkedList *cur = obj->next; //obj不存储有效数据,因此从next开始计数 while(cur) { if(count == index) { //实现删除 cur->prev->next = cur->next; //如果cur的下一个节点为空,那么就不需要将cur下一个节点的prev指针指向cur前一个节点的操作(因为NULL没有prev) if(cur->next) cur->next->prev = cur->prev; free(cur); return; } count++; cur = cur->next; } return; } //销毁链表 void myLinkedListFree(MyLinkedList* obj) { MyLinkedList *cur = obj->next; while(cur && cur->next) { MyLinkedList *temp = cur; //保存cur节点,便于销毁 //重新链接链表 cur->next->prev = cur->prev; cur->prev->next = cur->next; cur = cur->next; free(temp); } free(cur); //销毁最后一个有效节点 obj->next = NULL; //将哨兵位的next指针置空 }