带表头节点的双向循环链表编程
2016-11-08 10:39
519 查看
在单链表中,我们设了next指针,这使得我们查找下一个结点的时间复杂度为O(1),但是如果我们想要查找的是上一个结点,那么最坏的时间复杂度为O(n),因为我们每次都要从头开始遍历查找。
为了克服单向性这一缺点,便有人设计出了双向链表。双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。
双向循环链表中的指针都是成对出现的:你的next指向我,我的prior指向你。
为了克服单向性这一缺点,便有人设计出了双向链表。双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。
双向循环链表中的指针都是成对出现的:你的next指向我,我的prior指向你。
例子: /***************************************************** Funcion List: 实现带表头节点的双向链表的 头插,尾插,中间插,倒序,释放 *****************************************************/ #include <stdio.h> #include <stdlib.h> /* ================= 定义链表数据结构 ================= */ struct node { int num; struct node * next; struct node * prior; }; typedef struct node Node; typedef struct node * Link; /* =============== 功能:设头结点 返回:void =============== */ void creat_link(Link * head) { (*head) = (Link)malloc(sizeof(Node)) ; //创建一个新的节点,返回其地址 if(NULL == (*head)) { printf("malloc error!\n"); exit(-1); } (*head) -> next = *head; (*head) -> prior = *head; } /* ===================== 功能:从头部插入结点 返回:void ===================== */ void insert_node_head(Link * head,Link new_node) { Link tmp = *head; new_node->next = (*head)->next; (*head)->next->prior = new_node; new_node->prior = *head; (*head 4000 )->next = new_node; if((*head) -> prior == *head) { (*head)->prior = new_node; } } /* ===================== 功能:从尾部插入结点 返回:void ===================== */ void insert_node_tail(Link * head,Link new_node) { Link tmp; tmp = *head; while(tmp->next != (*head)) // while(tmp != NULL) { // { tmp = tmp-> next; // tmp = tmp-> next; 此时已经已经指向NULL } // } tmp -> next = new_node; new_node -> next = *head; new_node -> prior = tmp; (*head) -> prior = new_node; /* 更好的写法 */ //head->prior->next = newnode; //newnode->prior = head->prior; //newnode->next = head; //head->prior = newnode; } void insert_node_mid(Link * head,Link new_node,int num) //插入节点 { Link tmp = (*head)->next; if(*head == (*head)->next) { printf("link is empty !\n"); return; } else { while(tmp -> num != num && tmp -> next != (*head)) //找到要插入的位置 { tmp = tmp -> next; } if(tmp -> num == num) //判断这个位置是否为真的节点 { new_node -> next = tmp -> next; new_node -> prior = tmp ; tmp -> next -> prior = new_node; tmp ->next = new_node; } else { printf("no such node!\n"); } } } void delete_node(Link * head,int num_delete) { Link tmp = (*head)->next; Link p = NULL; if((*head) == tmp) { printf("link is empty !\n"); return; } else { while(tmp -> num != num_delete && tmp -> next != NULL) { p = tmp; //需要一个指针用于跟踪 tmp = tmp -> next; } if(tmp -> num == num_delete) //找到这个位置 { /*if( tmp == (*head)->next) { tmp -> next -> prior = (*head); (*head) -> next = tmp -> next; free(tmp); } else if(tmp -> next == (*head)) { p -> next = (*head); (*head) -> prior = p; free(tmp); } else { tmp -> next -> prior = p; p -> next = tmp -> next; free(tmp); }*/ tmp->prior->next = tmp->next; tmp->next->prior = tmp->prior; free(tmp); //释放 tmp = NULL; //置空 } else { printf("no such node!\n"); } } } void revers_link(Link * head) { Link p1,p2,p3; Link tmp = (*head)->next; if((*head) -> next == (*head)) return; else if((*head) -> next -> next == (*head)) { (*head) -> next = tmp -> next; tmp -> next -> next= tmp; tmp -> next = (*head); return; } else { p3 = tmp; p2 = p3 -> next; p1 = p2 -> next; while(p1 -> next != (*head)) { p2 -> next = p3; p2 -> prior = p1; p3 = p2; p2 = p1; p1 = p1->next; } p2 -> next = p3; p2 -> prior = p1; p1 -> next = p2; p1 -> prior = (*head); (*head) -> next -> next = (*head); (*head) -> next = p1; } } void free_node(Link * head) { Link tmp = (*head)->next; Link p = *head; if( tmp == (*head)) { printf("link is emtpy\n"); return; } while( (*head)->next != (*head)) { tmp = (*head)->next; (*head) ->next = tmp -> next; (*head) ->next -> prior = (*head); free(tmp); } /*仍然需要构成环*/ (*head) -> next = (*head); (*head) -> prior = (*head); printf("Link is freed\n"); } void display(Link head) { Link tmp; tmp = head -> next; if(head == head -> next) { printf("Link is empty\n"); } while(tmp != head) { printf("num = %d\n",tmp->num); tmp = tmp -> next; } } int main() { Link head = NULL; Link new_node = NULL; int i; int num_insert,num_delete; creat_link(&head); //创建用于指向表头结点的Link型指针(头指针),此时指向NULL。 for(i = 0; i <10; i++) { new_node = (Link)malloc(sizeof(Node)) ; //创建一个新的节点,返回其地址 if(NULL == new_node) { printf("malloc error!\n"); exit(-1); } new_node -> num = i; //节点赋值 insert_node_head(&head,new_node); //插入节点 // insert_node(&head,new_node,new_node->num); // insert_node_tail(&head,new_node); //插入节点(尾插) } display(head); printf("请输入要插入的序号:"); scanf("%d",&num_insert); new_node = (Link)malloc(sizeof(Node)) ; //创建一个新的节点,返回其地址 if(NULL == new_node) { printf("malloc error!\n"); exit(-1); } new_node -> num = 321; //节点赋值 insert_node_mid(&head,new_node,num_insert); //插入节点(中间) display(head); printf("请输入要删除的序号:"); scanf("%d",&num_delete); delete_node(&head,num_delete); display(head); printf("------------\n"); revers_link(&head); display(head); printf("------------\n"); free_node(&head); printf("------------\n"); display(head); printf("------------\n"); return 0; }
相关文章推荐
- 带表头节点的循环双向链表(头插,尾插,中间插,清除,前向显示,后向显示)
- 带表头节点的单向循环链表编程
- 复习下C 链表操作(双向循环链表,查找循环节点)
- 不带表头的单向链表,带表头的单向链表,带表头的单向循环链表,带表头的双向循环链表。
- 带表头结点的双向循环链表
- 如何创建不带头节点的双向循环链表
- 用只含一个链域的节点实现循环链表的双向遍历
- 双向循环带头节点链表
- 不带表头节点的循环单向链表
- 带头节点带环的双向循环链表
- 带头尾节点的双向循环链表
- 数据结构示例之带头节点的双向循环链表
- 带表头结点的双向循环链表
- 删除两个双向循环链表中具有相同值的节点
- 链表(单链表,带表头的链表,单向循环链表,双向循环链表)
- 数据结构示例之带头节点的双向循环链表
- 不带表头节点的单链表编程(2)
- 数据结构编程笔记六:第二章 线性表 双向循环链表的实现
- 【C++】模板实现带头节点的双向循环链表
- 带表头结点的双向循环链表