数据结构也不是那么没意思之双向循环链表
2016-06-30 14:06
375 查看
写数据结构的时候一定要注意 时刻在头脑中保存多个自己要写的数据结构的模型
:
1、头插入模型
2、尾插入模型
3、中间插入模型
4、对应的三个删除模型
双向循环链表的基本思路就是搞清楚
a、xx节点的后继的前驱
b、xx节点的后继
c、xx节点的前驱的后继
d、xx节点的前驱
弄明白了这几个知识点问题迎刃而解(ab和cd可以选取这俩模式其中的一种来写双链表即可)
例如:
p->front->next = pnew; //这种模式插入后p向右偏移1
p->front = pnew;
//p->next->front = pnew; 这种模式插入后p向左偏移1
//p->next = pnew;
下面是全部的代码
Linux 3.10.0-229.el7.x86_64下可通过G++
:
1、头插入模型
2、尾插入模型
3、中间插入模型
4、对应的三个删除模型
双向循环链表的基本思路就是搞清楚
a、xx节点的后继的前驱
b、xx节点的后继
c、xx节点的前驱的后继
d、xx节点的前驱
弄明白了这几个知识点问题迎刃而解(ab和cd可以选取这俩模式其中的一种来写双链表即可)
例如:
p->front->next = pnew; //这种模式插入后p向右偏移1
p->front = pnew;
//p->next->front = pnew; 这种模式插入后p向左偏移1
//p->next = pnew;
下面是全部的代码
Linux 3.10.0-229.el7.x86_64下可通过G++
/************************************************************************* > File Name: a.cpp > Author: ma6174 > Mail: ma6174@163.com > Created Time: Wed 29 June 2016 11:54:56 AM CST ************************************************************************/ #include<iostream> #include <stdio.h> #include <stdlib.h> class List { private: class Node { public: Node(); int number; Node *front; Node *next; }; public: List(); Node* malloc_node(); //分配内存空间 int free_node(Node *); //释放内存空间 bool yes_or_no(Node *); //检测内存空间是否分配成功 bool empty(); //判断链表是否为空 真代表空 假代表非空 int length(); //判断链表长度 int head_insert(); //头插入 int tail_insert(); //尾插入 int set_insert(); //任意位置插入 int head_delete(); //头删除 int tail_delete(); //尾删除 int set_delete(); //任意位置删除 int clear_List(); //清空链表内所有节点(非销毁) int destory_list(); //销毁链表 void print_list(); //打印链表 private: Node *head; Node *tail; Node *pnew; }; int main() { List a; a.head_insert(); a.print_list(); a.tail_insert(); a.print_list(); a.set_insert(); a.print_list(); a.head_delete(); a.print_list(); a.tail_delete(); a.print_list(); a.set_delete(); a.print_list(); return 0; } List::Node::Node() : number(-9999), front(NULL), next(NULL) { ; } List::List() { int count = 0; printf("请输入要初始化的节点个数:\n"); scanf("%d", &count); if (count <= 0) { printf("error1\n"); exit(0); } if (yes_or_no(head = malloc_node())) { //循环双向链表为空的时候头节点应该自己指向自己 head->number = 0; //在头节点中记录链表总节点个数 head->front = head; head->next = head; tail = head; for (int i = 0; i < count; ++i) { if (yes_or_no(pnew = malloc_node())) { //插入思路就是《大话数据结构》83页的图1 还是那句话写数据结构之前脑子里要有对应的小模型 //这里选用的是尾插入模式概念 pnew->front = tail; //新节点的前驱指向尾节点 pnew->next = tail->next; //新节点的后继指向尾节点的下一个节点 tail->next->front = pnew; //尾节点的下一个节点的前驱指向新节点 tail->next = pnew; //原本尾节点的后继指向新节点 tail = pnew; //修正尾节点的位置 } else { exit(1); } } head->number = count; //更新总节点数 } else { exit(1); } } List::Node* List::malloc_node() { return new Node; } int List::free_node(Node *node) { if (node != NULL) { delete node; node = NULL; --head->number; return 0; } printf("error2\n"); return 1; } bool List::yes_or_no(Node *node) { return node != NULL ? true : false; } bool List::empty() { return head != tail ? true : false; } int List::length() { return head->number; } int List::head_insert() //需要改变:pnew节点的前驱和后继 头节点的后继的的前驱 头节点的后继 (后两者顺序不可改变) { printf("头插入模式-》请输入要插入的数据:\n"); if (yes_or_no(pnew = malloc_node())) { scanf("%d",&pnew->number); pnew->front = head; //因为是头插入模式所以pnew的前驱指向头节点 pnew->next = head->next; //pnew的后继指向原链表中第一个节点(非头节点) head->next->front = pnew; //原本第一个节点的前驱指向pnew head->next = pnew; //头节点的后继指向pnew ++head->number; return 0; } printf("error3\n"); return 1; } int List::tail_insert() //需要改变:pnew节点的前驱和后继 尾节点的后继节点的前驱 尾节点的后继 (后两者顺序不可改变) { printf("尾插入模式-》请输入要插入的数据:\n"); if (yes_or_no(pnew = malloc_node())) { scanf("%d", &pnew->number); pnew->front = tail; //pnew的前驱指向尾节点 pnew->next = tail->next; //pnew的后继指向尾节点的下一个节点也就是头节点 tail->next->front = pnew; //尾节点的下一个节点(也就是头节点)的前驱指向pnew tail->next = pnew; //原本尾节点的后继指向pnew tail = pnew; //更新尾节点的指向 ++head->number; return 0; } printf("error4\n"); return 1; } int List::set_insert() { int location = 0; printf("请输入要插入的位置:\n"); scanf("%d", &location); if (location <= 0) { printf("error5\n"); return 1; } if (location == 1) //表明要插入在表头 { head_insert(); } else if (location >= head->number) //表明要插入在表尾 { tail_insert(); } else //表明要插入在location-1处的节点 和 location处的节点的中间 //需要改变:pnew节点的前驱和后继 location处节点前驱的后继 location处节点的前驱 (后两者顺序不可改变) { printf("请输入要插入的数据:\n"); if (yes_or_no(pnew = malloc_node())) { scanf("%d", &pnew->number); Node *p = head->next; //临时变量指向第一个节点 for (int i = 1; i < location && p != head; ++i, p = p->next) //找到要插入的位置 i为1而不是0是因为元素个数开始是1而不是0 { ;//p表示要插入的位置 } pnew->front = p->front; pnew->next = p; p->front->next = pnew; //这种模式插入后p向右偏移1 p->front = pnew; //p->next->front = pnew; 这种模式插入后p向左偏移1 //p->next = pnew; ++head->number; return 0; } } printf("error6\n"); return 1; } int List::head_delete() { Node *p = head->next; printf("头删除模式\n"); p->next->front = head; //第一个节点的下一个节点的前驱指向头节点 head->next = p->next; //头节点的后继指向第一个节点的下一个节点 free_node(p); return 0; } int List::tail_delete() { Node *p = tail; printf("尾删除模式\n"); tail->front->next = head; //最后一个节点的上一个节点的后继指向头节点 head->front = tail->front; //头节点的前驱指向最后一个节点的上一个节点 tail = head->front; //修正尾节点的位置 这就是循环双链表的好处 free_node(p); return 0; } int List::set_delete() { Node *p = head->next; int number = -9999; printf("请输入要删除的元素:\n"); scanf("%d", &number); if (head->next->number == number) //表明要删除的元素在链表头 { head_delete(); } else if (head->front->number == number) //表明要删除的元素在链表尾 { tail_delete(); } else //表明要删除的元素在链表中间 { while (p->next != head && p->number != number) { p = p->next; //p表示要删除的节点位置 } p->front->next = p->next; //要删除的节点的前一个节点的后继指向了要删除的节点的下一个节点 例如1 2 3 要删除2 那么1的后继要指向3 p->next->front = p->front; //要删除的节点的下一个节点的前驱指向了要删除的节点的前一个节点 例如1 2 3 要删除2 那么3的前驱要指向1 free_node(p); } return 0; } int List::clear_List() { for (Node *p = head->next; p != head; p=p->next) { p->number = -9999; } return 0; } int List::destory_list() { for (Node *p = head->next, *q = p; q != head; p = q) { q = p->next; free_node(p); } return 0; } void List::print_list() { printf("链表中总节点数为: %d\n", head->number); for (Node *p = head->next; p != head; p = p->next) { printf("双向循环链表中的元素为: %d\n", p->number); } }
相关文章推荐
- [C/C++]反转链表
- C#数据结构之顺序表(SeqList)实例详解
- C#实现基于链表的内存记事本实例
- Lua教程(七):数据结构详解
- C#模拟链表数据结构的实例解析
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- C语言实现带头结点的链表的创建、查找、插入、删除操作
- C++利用静态成员或类模板构建链表的方法讲解
- C++实现简单的学生管理系统
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Linux内核链表实现过程
- C++链表倒序实现方法
- C#通过链表实现队列的方法