雙向循環鏈表與單向循環鏈表的區別在於,每個節點的指針域中除了有指向下一結點的next指針外,還有指向前一結點的prev指針:
在鏈表中,中間部分結點的next指針指向其直接後繼結點,prev指針指向其直接前繼結點。與單向循環鏈表相同,末結點的next指針不再指向NULL,而是指向頭結點Head,而頭結點的prev則指向末結點。
將新結點new插入到p所指向的結點之後:
- ① new->prev = p;
- ② new->next = p->next;
- ③ p->next = new;
- ④ new->next->prve = new;
刪除p結點:
- ① p->prev->next = p->next;
- ② p->next->prev = p->prev;
- ③ free(p);
雙向循環鏈表的實現:
功能:在鏈表的結點中分別存放1、2、3、4、5、6、7、8、9、10,並進行相關操作,實現奇數升序偶數降序,即1、3、5、7、9、10、8、6、4、2。
基本思路:
從末結點向前遍歷,從遍歷到的第二個偶數結點開始,將偶數結點移動至末結點。
- #include <stdio.h>
- #include <stdlib.h>
- typedef int datatype;
- typedef struct node
- {
- datatype data;
- struct node *prev;
- struct node *next;
- }dlistnode, *dlinklist;
- //初始化
- dlinklist init_list(void)
- {
- dlinklist head = (dlinklist)malloc(sizeof(dlistnode));
- head->prev = head;
- head->next = head;
- return head;
- }
- //插入新結點
- void insert(dlinklist head, datatype i)
- {
- dlinklist newnode = (dlinklist)malloc(sizeof(dlistnode));
- //直接改指針,不需要遍歷,不需要中間結點。
- newnode->data = i;
- newnode->prev = head->prev;
- newnode->next = head;
- newnode->prev->next = newnode;
- head->prev = newnode;
- }
- void show(dlinklist head)
- {
- dlinklist p = head->next;
- while(p != head)
- {
- printf("%d\t", p->data);
- p = p->next;
- }
- printf("\n");
- }
- //升降序操作:
- void rearrange(dlinklist head)
- {
- dlinklist p, q;
- int i = 0;
- for(p=head->prev; p != head; p=p->prev)
- {
- //從末結點往前遍歷,從第二個偶數開始,將偶數結點搬移到末結點
- if(p->data % 2 == 0 && i != 0)
- {
- p->prev->next = p->next;
- p->next->prev = p->prev;
- p->prev = head->prev;
- p->next = head;
- head->prev->next = p;
- head->prev = p;
- //由於p所指的結點已成爲末結點,爲避免歷遍出錯,將p指向最近歷遍的奇結點。
- p = q;
- }
- //記錄最近歷遍奇數結點位置
- q = p;
- i++;
- }
- }
- int main(void)
- {
- dlinklist head;
- int n;
- int i;
- head = init_list();
- scanf("%d", &n);
- for(i=1; i<=n; i++)
- {
- insert(head, i);
- }
- show(head);
- rearrange(head);
- show(head);
- return 0;
- }