双向链表写的少,总是忘记指定一个结点的前驱。
头文件:
#include <iostream>
using namespace std;

typedef struct Node
{//结点结构
  int value;
  struct Node *pre,*next;//前驱指针和后继指针
}Node,*Link;

typedef struct List
{//链表结构
  Link head,tail;
  int length;
}List,*LinkList;

LinkList NewList(void)
{//构造一个空的链表
  LinkList list;
  list=new List;
  list->head=list->tail=NULL;
  list->length=0;
  return list;
}

int ListLength(List list)
{
  return list.length;
}

bool IsListEmpty(List list)
{
  if(list.length==0)
    return true;
  return false;
}

void ClearList(LinkList list)
{//清空链表,并释放每个结点的空间
  Link p,q;
  p=list->head;
  while(p!=list->tail)
  {
    q=p->next;
    free(p);
    p=q;
  }
  free(p);//释放尾结点
  list->tail=list->head=NULL;
  list->length=0;
}

void DestroyList(LinkList list)
{
  ClearList(list);
  free(list->head);
  free(list->tail);
}

void InsertElemToList(LinkList list,int pos,int elem)
{
  Link p;
  p=new Node;
  p->value=elem;
  if(pos<1 || pos>ListLength(*list)+1)
    cout<<"The position is invalidate."<<endl;
  else
  {
    if(pos==1)
    {//插在表头
      if(IsListEmpty(*list))
      {
        list->head=list->tail=p;
        p->next=NULL;
      }
      else
      {
        p->next=list->head;
        list->head->pre=p;
        list->head=p;
      }
    }
    else if(pos==ListLength(*list)+1)
    {//插在表尾
      list->tail->next=p;
      p->pre=list->tail;
      list->tail=p;
      p->next=NULL;
    }
    else
    {
      Link q=list->head;
      for(int i=1;i<pos-1;++i)
      {//找到pos-1位置的结点
        q=q->next;
      }
      p->next=q->next;
      p->pre=q;
      q->next->pre=p;
      q->next=p;
    }
    ++list->length;
  }    
}

void DeleteElemFromList(LinkList list,int pos,int &elem)
{
  if(IsListEmpty(*list))
  {
    cout<<"The list is empty,you can't delete element."<<endl;
  }
  else
  {
    if(pos<1 || pos>ListLength(*list))
    {//删除位置不正确
      cout<<"The position is invalidate."<<endl;
      return;//如果条件不成立,就结束
    }
    else
    {
      if(pos==1)
      {//删除表头
        if(ListLength(*list)==1)
        {//表长为1
          Link p=list->head;
          list->head=list->tail=NULL;
          elem=p->value;
          free(p);
        }
        else
        {//表长大于1
          Link p=list->head;
          list->head=p->next;
          p->next->pre=NULL;
          elem=p->value;
          free(p);
        }
      }
      else if(pos==ListLength(*list))
      {//删除表尾
        Link q=list->tail;
        list->tail=q->pre;
        list->tail->next=NULL;
        elem=q->value;
        free(q);
      }
      else
      {
        Link p=list->head;
        for(int i=1;i<pos;++i)
        {//找到pos位置的结点
          p=p->next;
        }
        p->pre->next=p->next;
        p->next->pre=p->pre;
        elem=p->value;
        free(p);
      }
      --list->length;
    }    
  }
}

bool PreElem(List list,int pos,int &elem)
{//判断 pos位置的结点有无前驱,若有则将其值存入elem
  if(pos<1 || pos>ListLength(list))
  {
    cout<<"The position is invalidate."<<endl;
    return false;
  }
  else    
  {
    if(pos==1)
    {
      cout<<"This position doesn't have a pre_element."<<endl;
      return false;
    }
    else
    {
      Link p=list.head;
      for(int i=1;i<pos;++i)
      {//找到pos位置处结点
        p=p->next;
      }
      elem=p->pre->value;
      return true;
    }
  }
}

bool NextElem(List list,int pos,int &elem)
{
  if(pos<1 || pos>ListLength(list))
  {
    cout<<"The position is invalidate."<<endl;
    return false;
  }
  else    
  {
    if(pos==ListLength(list))
    {
      cout<<"This position doesn't have a next_element."<<endl;
      return false;
    }
    else
    {
      Link p=list.head;
      for(int i=1;i<pos;++i)
      {//找到pos位置处结点
        p=p->next;
      }
      elem=p->next->value;
      return true;
    }
  }
}

bool CurrentElem(List list,int pos,int &elem)
{
  if(pos<1 || pos>ListLength(list))
  {
    cout<<"The position is invalidate."<<endl;
    return false;
  }
  else
  {
    Link p=list.head;
    for(int i=1;i<pos;++i)
    {
      p=p->next;
    }
    elem=p->value;
    return true;
  }
}

bool GetHead(List list,int &elem)
{//如果链表不空,则返回表头元素,用elem接收
  if(IsListEmpty(list))
  {
    cout<<"The list is empty."<<endl;
    return false;
  }
  else
  {
    elem=list.head->value;
    return true;
  }
}

bool GetTail(List list,int &elem)
{//如果链表不空,则返回表尾元素,用elem接收
  if(IsListEmpty(list))
  {
    cout<<"The list is empty."<<endl;
    return false;
  }
  else
  {
    elem=list.tail->value;
    return true;
  }
}
void VisitElemFromList(List list)
{
  Link p=list.head;
  if(!IsListEmpty(list))
  {
    while(p)
    {
      cout<<p->value<<' ';
      p=p->next;
    }
    cout<<endl;
  }
}

测试代码:
#include "stdafx.h"
#include <conio.h>
#include "double_direction_list.h"

int _tmain(int argc, _TCHAR* argv[])
{
  LinkList list;
  list=NewList();
  if(IsListEmpty(*list))
    cout<<"The list is empty."<<endl;
  cout<<"The length of the list is:"<<ListLength(*list)<<endl;
  InsertElemToList(list,1,3);
  InsertElemToList(list,1,5);
  InsertElemToList(list,ListLength(*list)+1,8);
  VisitElemFromList(*list);
  InsertElemToList(list,-1,2);
  InsertElemToList(list,9,21);
  int elem;
  DeleteElemFromList(list,1,elem);
  VisitElemFromList(*list);
  InsertElemToList(list,1,22);
  InsertElemToList(list,1,45);
  InsertElemToList(list,4,23);
  InsertElemToList(list,ListLength(*list),90);
  InsertElemToList(list,ListLength(*list)+1,88);
  VisitElemFromList(*list);
  int e;
  if(GetHead(*list,e))
  {
    cout<<"The head_elem of the list is:"<<e<<endl;
  }
  if(GetTail(*list,e))
  {
    cout<<"The tail_elem of the list is:"<<e<<endl;
  }
  cout<<"The length of the list is:"<<ListLength(*list)<<endl;
  DeleteElemFromList(list,2,elem);
  VisitElemFromList(*list);
  DeleteElemFromList(list,ListLength(*list),elem);
  VisitElemFromList(*list);
  DeleteElemFromList(list,1,elem);
  VisitElemFromList(*list);
  if(GetHead(*list,e))
  {
    cout<<"The head_elem of the list is:"<<e<<endl;
  }
  if(GetTail(*list,e))
  {
    cout<<"The tail_elem of the list is:"<<e<<endl;
  }
  cout<<"The length of the list is:"<<ListLength(*list)<<endl;
  DeleteElemFromList(list,ListLength(*list)+1,elem);
  DeleteElemFromList(list,-2,elem);
  int temp;
  if(PreElem(*list,4,temp))
    cout<<"The pre_element of this position is:"<<temp<<endl;
  if(PreElem(*list,1,temp))
    cout<<"The pre_element of this position is:"<<temp<<endl;
  if(PreElem(*list,12,temp))
    cout<<"The pre_element of this position is:"<<temp<<endl;
  if(NextElem(*list,2,temp))
    cout<<"The nex_element of this position is:"<<temp<<endl;
  if(NextElem(*list,ListLength(*list),temp))
    cout<<"The next_element of this position is:"<<temp<<endl;
  if(NextElem(*list,-3,temp))
    cout<<"The next_element of this position is:"<<temp<<endl;
  if(CurrentElem(*list,2,temp))
    cout<<"The current_element of this position is:"<<temp<<endl;
  if(CurrentElem(*list,ListLength(*list)+2,temp))
    cout<<"The current_element of this position is:"<<temp<<endl;
  ClearList(list);
  DeleteElemFromList(list,1,temp);
  getch();
  return 0;
}

转载于:https://blog.51cto.com/toigel/570475

双向链表(不带头结点)相关推荐

  1. 双向链表(带头结点)

    带头结点双向链表的内存分布情况 头文件 #pragma once //双向链表 typedef struct DNode {int data;DNode* next;DNode* prio; }DNo ...

  2. 带头结点双向循环 -- 双向链表

    目录 一.双向链表初始化 二.尾插 问题1:什么时候传一级指针,什么时候传二级指针呢? 三.打印 四.尾删 五.头插 六.头删 七.pos之前插入 八.删除pos位置的节点 九.销毁链表 总代码: L ...

  3. 建立带头结点的双向链表_尾插法

    // ------------------------------------------------------- //2014--03--14 // 建立双向链表 // 程序分析:双向链表的节点有 ...

  4. c语言循环链表中设立尾链表,C语言实现双向非循环链表(带头结点尾结点)的节点插入...

    对于双向链表,个人推荐使用带头结点尾结点的方式来处理会比较方便.我在<C语言实现双向非循环链表(不带头结点)的节点插入>中详细实现了在不带头结点的情况下的插入.这次我们将会来在使用头结点尾 ...

  5. 双向链表中插入结点并输出

    [问题描述] 对带头结点的双向链表,实现插入算法. [输入形式] 第一行输入一个N(N大于等于1,小于1000): 第二行输入N个整数,以空格作为分隔,创建长度为N的双向链表,为双向输出方便,需保留头 ...

  6. C语言实现双向非循环链表(不带头结点)的基本操作

    双向链表也叫双链表,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任何一个节点开始,都可以很方便的访问它的前驱结点和后继节点.别人常常来构造双向循环链表,今天我们特立 ...

  7. 数据结构——带头结点双向循环链表

    相比较与单链表,双向循环链表每个结点多了一个prev指针域,用于指向该结点的前驱,并且链表的头尾结点也用指针域相连.所以对于带头结点的双向循环链表的判空条件为head->next=head;除此 ...

  8. 数据结构_带头结点的双向循环链表

    这篇博客整理带头结点的双向循环链表.带头结点的双向循环链表在进行操作的时候是要比单链表更方便的,比如说在尾删的时候,不需要遍历整个链表,头结点的上一个结点就是尾结点.凡是涉及到寻找尾结点的操作,都会比 ...

  9. java不带头结点单链表,java带头结点的单链表

    JAVA 循环双链表的建立 import java.util.Scanner; //循环双向链表的结点类 class DuLNode { private Object data;// 存放结点值 前驱 ...

  10. 带头结点的线性表的链式实现

    复习了顺序实现后,自己模仿着写了链式实现 /*** @author lirui 带头结点的线性表的链式实现*/ public class MyLinkList<T> {// 内部类LNod ...

最新文章

  1. two years in cnblogs.com
  2. python是一种语言还是一个软件-自动化专业想学一门语言 是学Python 还是Java ?...
  3. 第二十二讲 延迟定理
  4. Hardcoded string , should use @string resource警告 Tag start is not closed
  5. 让VS2013支持 C# 6.0 语法
  6. ROS中阶笔记(八):机器人SLAM与自主导航—机器人自主导航
  7. python 把函数作为参数 ---高阶函数
  8. [转载] 跟着吴恩达学机器学习(Machine Learning) on Coursera 第一天
  9. MySQL索引优化案例学习总结
  10. 移动端rem布局实践
  11. win10官方原版镜像系统
  12. 2019第十二届“认证杯”数学建模(第一阶段)
  13. php 启用ereg,PHP 5.3的ereg / eregi替换
  14. Java的triangle方法_java三角形类Triangle用法代码解析
  15. STM32单片机点亮流水灯
  16. java把小写变大写_用java实现人民币小写变大写的方法
  17. 齐二TK6916/20/26/32系列数控落地铣镗床简介7
  18. 中国手机支付行业竞争现状及市场发展格局分析报告2022-2028年版
  19. Snowboy 声音识别
  20. CSS语法及其选择器

热门文章

  1. typecho 邮件mail插件 LoveKKCommentModify 美化版
  2. 三分钟撸完前后端crypto-js加解密,你学废了吗?
  3. MooTools教程(3):数组管理DOM元素
  4. Magento教程 15:Magento 批次修改产品资料
  5. iOS7应用开发4、Foundation框架
  6. Magento报错“No Input File Specified”的解决方法
  7. 动态规划——矩阵连乘(算法设计课题)
  8. Linux head命令:显示文件开头的内容
  9. 【AI视野·今日NLP 自然语言处理论文速览 第二十六期】Wed, 3 Nov 2021
  10. 【AI视野·今日CV 计算机视觉论文速览 第208期】Fri, 28 May 2021