带表头节点的单向循环链表编程
2016-11-08 09:43
429 查看
对于单链表,由于每个结点只存储了向后的指针,到了尾标志就停止了向后的操作,这样,当某一个结点找不到前驱结点了,也不能回去找。而我们现在要解决这个问题,就要利用循环链表。
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
循环链表解决了一个很麻烦的问题:如何从一个结点出发,访问到链表的全部结点。
为了使空链表与非空链表处理一致,我们通常设一个头结点,当然,并不是说循环链表一定要有头结点。
其实循环链表和单链表的主要差异在于循环的判断条件上,之前是判断temp->next是否为空,现在是temp->next不等于头结点
知识点:
1.循环链表是单链表的变形。
2.循环链表最后一个结点的 link 指针不 为NULL,而是指向了表的前端。
3.为简化操作,在循环链表中往往加入表头结点。
4.循环链表的特点是:只要知道表中某一结点的地址,就可搜寻到所有其他结点的地址。
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
循环链表解决了一个很麻烦的问题:如何从一个结点出发,访问到链表的全部结点。
为了使空链表与非空链表处理一致,我们通常设一个头结点,当然,并不是说循环链表一定要有头结点。
其实循环链表和单链表的主要差异在于循环的判断条件上,之前是判断temp->next是否为空,现在是temp->next不等于头结点
知识点:
1.循环链表是单链表的变形。
2.循环链表最后一个结点的 link 指针不 为NULL,而是指向了表的前端。
3.为简化操作,在循环链表中往往加入表头结点。
4.循环链表的特点是:只要知道表中某一结点的地址,就可搜寻到所有其他结点的地址。
/***************************************************** copyright (C), 2014-2015, Lighting Studio. Co., Ltd. File name: Author:Jerey_Jobs Version:0.1 Date: Description: Funcion List: *****************************************************/ #include <stdio.h> #include <stdlib.h> struct node { int num; struct node * next; }; typedef struct node Node; typedef struct node * Link; void creat_link(Link * head) { (*head) = (Link)malloc(sizeof(Node)) ; //创建一个新的节点,返回其地址 if(NULL == (*head)) { printf("malloc error!\n"); exit(-1); } (*head) -> next = *head; } /* ========================= 功能:从链表头部插入结点 返回:void ========================= */ void insert_node_head(Link * head,Link new_node) { Link tmp = *head; new_node->next = tmp->next; tmp -> next = new_node; } /* ========================= 功能:从链表尾部插入结点 返回:void ========================= */ void insert_node_tail(Link *head,Link newnode) { Link temp = *head; while (temp->next != *head) //找到最后一个结点 { temp = temp->next; } temp->next = newnode; //插入结点 newnode->next = *head; } void insert_node(Link * head,Link new_node,int n) { Link tmp = NULL; Link q = NULL; tmp = *head; if(NULL == *head) //链表为空时 { new_node -> next = NULL; *head = new_node; //使头头指针指向最新的节点 } else //链表不为空时 { while((tmp->num) < n && (tmp->next != NULL)) // 寻找插入的位置 { q = tmp; tmp = tmp -> next; } if(((*head) -> next) == NULL) //只有一个节点时 { if(tmp->num < n) // 这个节点 小于 新节点时 { (*head)->next = new_node; new_node->next = NULL; } else //这个节点 大于 新的节点时 { new_node->next = *head; *head = new_node; } } else //不止一个节点时 { if(tmp == *head) //头处 { new_node->next = *head; *head = new_node; } else //非头处 { if(tmp->next != NULL) //非尾处 { q -> next = new_node; new_node -> next = tmp; } else // 尾处 { if(n > (tmp -> num)) // 新节点数据大于尾 { tmp -> next = new_node; new_node -> next = NULL; } else //新节点数据小于尾 { q -> next = new_node; new_node -> next = tmp; } } } } } } /* ========================= 功能:从链表指点节点后插入节点 返回:void ========================= */ 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) // { /*if((*head) -> next == tmp) { new_node -> next = tmp; (*head) -> next = new_node; } else */ if( tmp -> next == (*head)) /其实这个里考虑多余 { new_node -> next = (*head); tmp -> next = new_node; } else { new_node -> next = tmp -> next; tmp -> next = new_node; } } else { printf("no such node!\n"); } } } /* ========================= 功能:删除指定节点 返回:void ========================= */ 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) { (*head) -> next = tmp -> next; free(tmp); } else if(tmp -> next == (*head)) { p -> next = (*head); free(tmp); tmp = NULL; } else { p -> next = tmp -> next; free(tmp); tmp = NULL; } } else { printf("no such node!\n"); } } } /* ========================= 功能:从链表反转 返回:void ========================= */ 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; p3 = p2; p2 = p1; p1 = p1->next; } p2 -> next = p3; p1 -> next = p2; (*head) -> next -> next = (*head); (*head) -> next = p1; } } /* ========================= 功能:释放链表 返回:void ========================= */ 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; free(tmp); tmp = NULL; } tmp = (*head)->next; free(tmp); tmp = NULL; printf("Link is freed\n"); } /* ========================= 功能:打印 返回:void a957 ========================= */ 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); return 0; }
相关文章推荐
- 带表头节点的双向循环链表编程
- 带表头节点的循环单向链表
- 不带表头节点的循环单向链表
- 有头节点单向循环链表
- 带表头节点的单链表编程
- 不带表头的单向链表,带表头的单向链表,带表头的单向循环链表,带表头的双向循环链表。
- 判断带表头的单向循环链表La是否递增
- 不带表头节点的单链表编程(1)
- 单向循环链表的头插,尾插,中间插以及删除节点
- 无表头节点的单向链表
- 一个单向链表,只知道某个节点的指针p,但是p不是尾节点,请编程删除节点p.
- 复习下C 链表操作(单向循环链表、查找循环节点)
- 不带表头节点的单链表编程(2)
- 带表头的单向循环链表
- 【编程题目】求单向链表的倒数第k个节点——关于代码鲁棒性的探讨(C++实现)
- 带表头节点的循环双向链表(头插,尾插,中间插,清除,前向显示,后向显示)
- 链表(单链表,带表头的链表,单向循环链表,双向循环链表)
- 向有序循环单向链表中插入节点
- 单向带表头链表中找节点
- 单向链表中,如何在给定节点前快速插入一个节点?