头疼的算法与数据结构——双向循环链表
来源:互联网 发布:如何面试网络推广专员 编辑:程序博客网 时间:2024/05/17 08:46
一:双向循环链表的简介
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双链表的结构定义如下:
struct node{ int data;//数据域 struct node* next;//后继 struct node* pre;//前驱};
整体结构:
二:双向循环链的初始化
//创建链表void creatList(Node** h){ Node* pn=NULL;//存储新的节点 Node* p=NULL;//头节点的替身 int d; printf("请输入数据\n"); scanf("%d",&d); pn=creteNode(d); pn->next=NULL;//next指向空 pn->pre=NULL;//pre指向空 sum=1; *h=pn; p=*h; while(1) { printf("请输入数据\n"); scanf("%d",&d); if(d==0) { //创建到最后一个节点时,最后一个节点next为头节点 p->next=*h; (*h)->pre=p;//头节点的pre为最后一个节点 break; } pn=creteNode(d); p->next=pn; pn->pre=p; p=p->next; sum++;//元素个数++ }}
创建了一个链表。
三:插入操作
原理如图:
代码:
//头插法int addFont(int d,Node** h)//修改头节点 传入二级指针{ int i,n=sum; Node* pn=NULL; pn=creteNode(d); Node* p=*h; for(i=0;i<n-1;i++) { p=p->next; } //p为最后一个节点 pn->next=*h;//新节点成为头节点 p->next=pn;//最后一个节点p的下一个节点为新节点pn pn->pre=p;//新的头节点的pre为p (*h)->pre=pn;//原头节点的前一个节点为新节点 *h=pn;//新节点为头节点 sum++;}//插入int insertNode(int n,int d,Node** h)//在n位置插入d{ if((n<1)||(*h==NULL)||(n>sum)) { printf("插入位置不合法||链表为空!\n"); return 0; } Node* pn=creteNode(d);//创建新的节点 //插入位置为1,即插入头节点的位置 if(n==1) { addFont(d,h);//调用头插法 return 0; } else if(n==sum) { addBack(d,*h); return 0; } else { Node* pf=findNode(*h,n-1); //找到要删除的节点的前一个节点 pn->next=pf->next;//前一个节点的next等于新的节点的next pf->next->pre=pn;//pf的next节点的pre应该为pn pf->next=pn;//前一个节点的next等于新的节点 pn->pre=pf;//新节点的前一个节点为找到的前一个节点pf sum++; return 1; }}
四:删除操作
原理图:
代码:
//删除头节点int DelectFont(Node** h){ //DelectFont(h); int i, n1=sum; Node* p=*h; Node* pd=NULL;; for(i=0;i<n1-1;i++) { p=p->next; } //p为最后一个节点 pd=*h; *h=pd->next;//头节点的下一个节点成头节点 p->next=*h;//最后一个节点的next为头节点 (*h)->pre=p;//pd节点成为了头节点,它的前驱为p sum--;//元素个数-1 return 0;}//删除第n个位置的元素int deleteNode(int n,Node** h){ //int i;//循环变量 //判断头节点是否为空,位置是不是合法 if((*h==NULL)||(n<1)||(n>sum)) { printf("删除的链表为空||删除的位置不合法!so 插入失败\n"); return 0; } Node* pd=NULL; //删除头节点 if(n==1) { DelectFont(h); return 0; } //删除 //找到要删除的节点的前一个节点 Node* pf=findNode(*h,n-1); pd=pf->next;//将要删除的节点的给pd pf->next=pd->next;//将删除元素的前一个的next指向删除元素的后一个元素 pd->pre=NULL;//pd的pre指向空 pd->next->pre=pf;//将删除元素的后一个元素的前驱给pf pd->next=NULL;//pdnext指向空 sum--; return 1;}
五:整体代码
#include <stdio.h>#include <stdlib.h>struct node{ int data; struct node* next; struct node* pre;};typedef struct node Node;#define SIZE sizeof(Node)int sum;//节点个数Node* creteNode(int d);//创建节点void creatList(Node** h);//创建链表Node* findNode(Node* h,int n);//查找某个节点的位置int addBack(int d,Node* h);//末尾增加一个新的节点int addFont(int d,Node** h);//修改头节点 传入二级指针int insertNode(int n,int d,Node** h);//在n位置插入dint DelectFont(Node** h);//删除头节点int deleteNode(int n,Node** h);//删除第n个位置的元素void print(Node* h);//打印链表//创建节点Node* creteNode(int d){ Node* pn=(Node*)malloc(SIZE); pn->data=d; pn->next=NULL; pn->pre=NULL; return pn;}//创建链表void creatList(Node** h){ Node* pn=NULL;//存储新的节点 Node* p=NULL;//头节点的替身 int d; printf("请输入数据\n"); scanf("%d",&d); pn=creteNode(d); pn->next=NULL;//next指向空 pn->pre=NULL;//pre指向空 sum=1; *h=pn; p=*h; while(1) { printf("请输入数据\n"); scanf("%d",&d); if(d==0) { //创建到最后一个节点时,最后一个节点next为头节点 p->next=*h; (*h)->pre=p;//头节点的pre为最后一个节点 break; } pn=creteNode(d); p->next=pn; pn->pre=p; p=p->next; sum++;//元素个数++ }}//查找某个节点的位置Node* findNode(Node* h,int n){ int i; if((h==NULL)||(n<0)||(n>sum)) { printf("查找位置不合法||链表为空!\n"); return NULL; } if(n==1) { return h; } for(i=1;i<n;i++) { h=h->next; } return h;} //末尾增加一个新的节点int addBack(int d,Node* h){ int i,n=sum; Node *pn=NULL; pn=creteNode(d); Node* p=h; for(i=0;i<n-1;i++) { p=p->next; } //此时的p指向了最后一个元素 p->next=pn;//最后一个节点p的next为新节点 pn->pre=p;//新节点的前一个节点为p pn->next=h;//pn的最后一个节点为头节点 h->pre=pn;//头节点的pre为新节点 sum++;}//头插法int addFont(int d,Node** h)//修改头节点 传入二级指针{ int i,n=sum; Node* pn=NULL; pn=creteNode(d); Node* p=*h; for(i=0;i<n-1;i++) { p=p->next; } //p为最后一个节点 pn->next=*h;//新节点成为头节点 p->next=pn;//最后一个节点p的下一个节点为新节点pn pn->pre=p;//新的头节点的pre为p (*h)->pre=pn;//原头节点的前一个节点为新节点 *h=pn;//新节点为头节点 sum++;}//插入int insertNode(int n,int d,Node** h)//在n位置插入d{ if((n<1)||(*h==NULL)||(n>sum)) { printf("插入位置不合法||链表为空!\n"); return 0; } Node* pn=creteNode(d);//创建新的节点 //插入位置为1,即插入头节点的位置 if(n==1) { addFont(d,h);//调用头插法 return 0; } else if(n==sum) { addBack(d,*h); return 0; } else { Node* pf=findNode(*h,n-1); //找到要删除的节点的前一个节点 pn->next=pf->next;//前一个节点的next等于新的节点的next pf->next->pre=pn;//pf的next节点的pre应该为pn pf->next=pn;//前一个节点的next等于新的节点 pn->pre=pf;//新节点的前一个节点为找到的前一个节点pf sum++; return 1; }}//删除头节点int DelectFont(Node** h){ //DelectFont(h); int i, n1=sum; Node* p=*h; Node* pd=NULL;; for(i=0;i<n1-1;i++) { p=p->next; } //p为最后一个节点 pd=*h; *h=pd->next;//头节点的下一个节点成头节点 p->next=*h;//最后一个节点的next为头节点 (*h)->pre=p;//pd节点成为了头节点,它的前驱为p sum--;//元素个数-1 return 0;}//删除第n个位置的元素int deleteNode(int n,Node** h){ //int i;//循环变量 //判断头节点是否为空,位置是不是合法 if((*h==NULL)||(n<1)||(n>sum)) { printf("删除的链表为空||删除的位置不合法!so 插入失败\n"); return 0; } Node* pd=NULL; //删除头节点 if(n==1) { DelectFont(h); return 0; } //删除 //找到要删除的节点的前一个节点 Node* pf=findNode(*h,n-1); pd=pf->next;//将要删除的节点的给pd pf->next=pd->next;//将删除元素的前一个的next指向删除元素的后一个元素 pd->pre=NULL;//pd的pre指向空 pd->next->pre=pf;//将删除元素的后一个元素的前驱给pf pd->next=NULL;//pdnext指向空 sum--; return 1;}//打印链表void print(Node* h){ int i,n=sum; printf("list:\n"); Node* p=h; printf("正序遍历:\n"); for(i=1;i<=n;i++) { printf("%d ",p->data); p=p->next; } //上面遍历到第一个节点 printf("\n"); printf("反序遍历:\n"); for(i=1;i<=n;i++) { printf("%d ",p->pre->data); p=p->pre; } printf("\n");}int main(){ Node* head=NULL; creatList(&head); deleteNode(2,&head); print(head); return 0;}
1 0
- 头疼的算法与数据结构——双向循环链表
- 头疼的算法与数据结构——循环链表详解
- 头疼的算法与数据结构——链表实现栈
- 头疼的算法与数据结构——单链表详解
- 头疼的算法与数据结构——红黑树
- 头疼的算法与数据结构——约瑟夫环
- 数据结构与算法——线性表链式存储(双向循环链表)
- 数据结构—循环链表与双向链表
- 数据结构 P35 算法实现 双向循环链表的创建
- <数据结构与算法>双向循环链表的全面基本框架(C语言描述)
- 数据结构 P36-37 算法实现 双向循环链表的插入与删除
- 数据结构之——循环双向链表的实现
- 数据结构与算法—循环链表
- 数据结构与算法Java版——双向链表
- 头疼的算法与数据结构——详解选择排序法
- 头疼的算法与数据结构——详解插入排序法
- 头疼的算法与数据结构——二维数组中的查找
- 头疼的算法与数据结构——八皇后问题(递归法)
- 博客网站(1)-基本认识与博客项目的创建
- java——方法
- tomcat和JDK环境变量配置
- Maximum Subarray
- Two Sum
- 头疼的算法与数据结构——双向循环链表
- leetcode258 Add Digits java
- C#多线程
- 从零开始配置搬瓦工
- matlab中mcc、mbuild和mex命令详解
- ubuntu 16.04[LTS] Shadowsocks + ProxyChain +Genpac 配置方法
- 颜色值、长度值
- 1——进程控制
- Java学习日记5:jsp
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
中天公棚
中天盛祥
中天悬剑
中天房车
中天门
吴中天
中天吾乡
中天钢铁
中天人力
少中天
中天门旅游
中天之世
st中天
新壶中天
st中天股吧
中天镇
中天城投
中天招聘
壶中天
中天电视
王中天
中天合创
中天贵金属
中天房地产
中天同花顺
下中天
皓月中天
中天建设集团有限公司
中天建设集团有限
中天建设集团
中天金融股吧
中天科技股吧
中天能源股吧
中天金融股票
中天人力资源网
中天人力资源
中天科技集团
河源中天赛鸽公棚
江苏中天科技股份有限公司
000540中天金融
中天盛祥科技有限公司