双向循环链表与单向循环链表的区别在于,每个节点的指针域中除了有指向下一结点的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;
- }
原文:http://blog.csdn.net/SahPah/article/details/38534923