C++ 雙鏈表的基本操作(詳解)
1.概念
雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數(shù)據(jù)結(jié)點(diǎn)中都有兩個指針,分別指向直接后繼和直接前驅(qū)。所以,從雙向鏈表中的任意一個結(jié)點(diǎn)開始,都可以很方便地訪問它的前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)。一般我們都構(gòu)造雙向循環(huán)鏈表。
結(jié)構(gòu)圖如下所示:
2.基本操作實例
DoubleList.cpp
#include "stdafx.h"
#include "DoubleList.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
DoubleList::DoubleList()
{
    pDoubleListNode pDouList = NULL;
    // 創(chuàng)建雙鏈表
    CreateDouList(pDouList);
    PrintDouList(pDouList);
    // 打印逆序鏈表
    PrintDouReverseList(pDouList);
    // 節(jié)點(diǎn)后插入節(jié)點(diǎn)
    InsertNodeAfter(pDouList);
    PrintDouList(pDouList);
    // 節(jié)點(diǎn)前插入節(jié)點(diǎn)
    InsertNodeBefore(pDouList);
    PrintDouList(pDouList);
    // 刪除節(jié)點(diǎn)
    DeleteNode(pDouList);
    PrintDouList(pDouList);
    // 刪除鏈表
    DeleteDouList(pDouList);
    PrintDouList(pDouList);
    system("PAUSE");
}
DoubleList::~DoubleList()
{
}
//創(chuàng)建雙向鏈表
void DoubleList::CreateDouList(pDoubleListNode &head)
{
  char x;     // 定義成char型是用于輸入'q'時可以退出,其實定義成int也能退出
  pDoubleListNode p, s;
  head = (pDoubleListNode)malloc(sizeof(DoubleListNode));
  head->next = NULL;
  head->prior = NULL;    // 構(gòu)造頭結(jié)點(diǎn)p
  p = head;
  printf("\n輸入雙向鏈表的元素,每輸入一個元素后按回車,輸入q表示結(jié)束.\n");
  fflush(stdin);  //清空輸入緩沖區(qū)
  x = getchar();
  while (x != 'q')
  {
    s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
    s->data = x - '0'; // 得到的是輸入字符的ASCII碼,減去30H就變成想要的數(shù)字
    s->next = NULL;
    s->prior = p;
    p->next = s;
    p = s;
    fflush(stdin);
    x = getchar();
  }
  if (x == 'q')
  {
    printf("雙向鏈表構(gòu)造完畢!\n");
  }
}
//打印雙向鏈表
void DoubleList::PrintDouList(pDoubleListNode &head)
{
  pDoubleListNode p;
  printf("\n打印出雙向鏈表數(shù)據(jù)為:\n");
  if (!IsDouListEmpty(head))
  {
    p = head->next;
    while (p)
    {
      printf("%d\n", p->data);
      p = p->next;
    }
  }
}
//逆序打印雙向鏈表
void DoubleList::PrintDouReverseList(pDoubleListNode &head)
{
  pDoubleListNode p;
  printf("\n打印出逆序雙向鏈表數(shù)據(jù)為:\n");
  if (!IsDouListEmpty(head))
  {
    p = head->next;
    while (p->next)
    {
      p = p->next;
    }
    while (p->prior)
    {
      printf("%d \n", p->data);
      p = p->prior;
    }
  }
}
//求鏈表長度
int DoubleList::GetDouListLength(pDoubleListNode &head)
{
  int length = 0;
  if (head == NULL)
  {
    printf("鏈表不存在,請先初始化!\n");
  }
  else
  {
    pDoubleListNode p = head->next;
    while (p)
    {
      length++;
      p = p->next;
    }
  }
  return length;
}
//判斷鏈表是否為空
bool DoubleList::IsDouListEmpty(pDoubleListNode &head)
{
  if (head == NULL)
  {
    printf("鏈表不存在,請先初始化!\n");
    return true;
  }
  else if (head->next == NULL)
  {
    printf("鏈表為空!\n");
    return true;
  }
  
  return false;
}
//把雙向鏈表置空
void DoubleList::ClearDouList(pDoubleListNode &head)
{
  if (head == NULL)
  {
    printf("鏈表不存在,請先初始化!\n");
  }
  else
  {
    pDoubleListNode p, q;
    p = q = head->next;  //是p、q指向第一個元素
    head->next = NULL;
    while (p)     //逐個釋放元素所占內(nèi)存
    {
      p = p->next;
      free(q);
      q = p;
    }
  }
}
// 刪除雙向鏈表
void DoubleList::DeleteDouList(pDoubleListNode &head)
{
  printf("\n刪除雙向鏈表\n");
  ClearDouList(head);
  free(head);
  head = NULL;
}
// 在雙向鏈表中第i個位置后面插入元素
void DoubleList::InsertNodeAfter(pDoubleListNode &head)
{
  int data, pos;
  pDoubleListNode p, s;
  p = head;
  int i = 0;
  printf("\n在雙向鏈表中第i個位置后面插入元素\n");
  printf("請輸入要插入的元素和位置:\n");
  scanf_s("%d%d", &data, &pos, 100);
  if (head == NULL)
  {
    printf("鏈表不存在,請先初始化!\n");
  }
  else if (head->next == NULL)
  {
    printf("鏈表為空,插入第一個元素!\n");
    s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
    s->data = data;
    s->prior = NULL;  
    s->next = NULL;
    head->next = s;    // 將新結(jié)點(diǎn)插入head后 
  }
  else if (pos<1 || pos>GetDouListLength(head) + 1)
  {
    printf("插入位置錯誤!\n");
  }
  else
  {
    while (i < pos)
    {
      p = p->next;
      i++;
    }
    if (i == GetDouListLength(head))   //如果在最后一個元素后面插入data
    {
      s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
      s->data = data;
      s->next = NULL;
      s->prior = p;
      p->next = s;
    }
    else
    {
      s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
      s->data = data;
      s->next = p->next;
      p->next->prior = s;
      p->next = s;
      s->prior = p;
    }
  }
}
// 在雙向鏈表中第i個位置前面插入元素
void DoubleList::InsertNodeBefore(pDoubleListNode &head)
{
  int data, pos;
  pDoubleListNode p, s;
  p = head;
  int i = 0;
  printf("\n在雙向鏈表中第i個位置前面插入元素\n");
  printf("請輸入要插入的元素和位置:\n");
  scanf_s("%d%d", &data, &pos, 100);
  if (head == NULL)
  {
    printf("鏈表不存在,請先初始化!\n");
  }
  else if (head->next == NULL)
  {
    printf("鏈表為空,插入第一個元素!\n");
    s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
    s->data = data;
    s->prior = NULL;
    s->next = NULL;
    head->next = s;    // 將新結(jié)點(diǎn)插入head后 
  }
  else if (pos<1 || pos>GetDouListLength(head) + 1)
  {
    printf("插入位置錯誤!\n");
  }
  else
  {
    while (i < pos)
    {
      p = p->next;
      i++;
    }
    if (i == 1)   // 如果在第一個元素前面插入data
    {
      s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
      s->data = data;
      head->next = s;    // 將新結(jié)點(diǎn)插入head后 
      s->prior = head;    // 新結(jié)點(diǎn)的前結(jié)點(diǎn)指向頭結(jié)點(diǎn) 
      s->next = p;            // 新結(jié)點(diǎn)的后結(jié)點(diǎn)指向原h(huán)ead的后結(jié)點(diǎn) 
      p->prior = s ;          // 原第一個結(jié)點(diǎn)的前結(jié)點(diǎn)指向新結(jié)點(diǎn) 
    }
    else
    {
      s = (pDoubleListNode)malloc(sizeof(DoubleListNode));
      s->data = data;
      s->prior = p->prior;
      s->next = p;
      p->prior->next = s;
      p->prior = s;
    }
  }
}
//刪除雙向鏈表中的第i個元素
void DoubleList::DeleteNode(pDoubleListNode &head)
{
  int pos;
  int i = 0;
  pDoubleListNode p = head;
  printf("\n在雙向鏈表中刪除第i個位置的元素\n");
  printf("請輸入要刪除的位置:");
  scanf_s("%d", &pos, 100);
  
  if (IsDouListEmpty(head))
  {
    return;
  }
  else if (pos<1 || pos>GetDouListLength(head))
  {
    printf("刪除的位置不存在!\n");
  }
  else
  {
    while (i < pos)
    {
      p = p->next;
      i++;
    }
    if (i == GetDouListLength(head))
    {
      p->prior->next = NULL;
      free(p);
    }
    else
    {
      p->prior->next = p->next;
      p->next->prior = p->prior;
      free(p);
    }
  }
}
DoubleList.h
#pragma once
typedef struct DoubleListNode
{
  int data;       //數(shù)據(jù)
  struct DoubleListNode *prior; //前驅(qū)
  struct DoubleListNode *next; //后繼
}DoubleListNode, *pDoubleListNode;
class DoubleList
{
public:
  DoubleList();
  ~DoubleList();
  //初始化雙向鏈表
  void DoubleList::CreateDouList(pDoubleListNode &head);
  //打印雙向鏈表
  void DoubleList::PrintDouList(pDoubleListNode &head);
  //逆序打印雙向鏈表
  void DoubleList::PrintDouReverseList(pDoubleListNode &head);
  //求鏈表長度
  int DoubleList::GetDouListLength(pDoubleListNode &head);
  //判斷鏈表是否為空
  bool DoubleList::IsDouListEmpty(pDoubleListNode &head);
  //把雙向鏈表置空
  void DoubleList::ClearDouList(pDoubleListNode &head);
  //刪除雙向鏈表
  void DoubleList::DeleteDouList(pDoubleListNode &head);
  //在雙向鏈表中第i個位置后面插入元素m
  void DoubleList::InsertNodeAfter(pDoubleListNode &head);
  // 在雙向鏈表中第i個位置前面插入元素
  void DoubleList::InsertNodeBefore(pDoubleListNode &head);
  //刪除雙向鏈表中的第i個元素
  void DoubleList::DeleteNode(pDoubleListNode &head);
};
3.對鏈表插入節(jié)點(diǎn)的理解
例如在節(jié)點(diǎn)i前插入一個新的節(jié)點(diǎn)(即上面代碼中的InsertNodeBefore函數(shù)):
typedef struct DoubleListNode
{
  int data;       // 數(shù)據(jù)
  struct DoubleListNode *prior; // 前驅(qū)
  struct DoubleListNode *next; // 后繼
}DoubleListNode, *pDoubleListNode;
假設(shè)該鏈表由五個節(jié)點(diǎn)構(gòu)成,分別為A,B,C,D,E
圖中假設(shè)了A,B,C,D,E的地址分別為:addressA,addressB,addressC,addressD,addressE。
下面將分析鏈表的前插的例子:
雙鏈表的前插,下面這是在節(jié)點(diǎn)"D"前插入一個新的節(jié)點(diǎn)"S"的代碼和分析
以上這篇C++ 雙鏈表的基本操作(詳解)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持我們。
上一篇:stringstream操縱string的方法總結(jié)
欄 目:C語言
下一篇:C++中4種強(qiáng)制類型轉(zhuǎn)換的區(qū)別總結(jié)
本文標(biāo)題:C++ 雙鏈表的基本操作(詳解)
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/1930.html
您可能感興趣的文章
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
 - 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對數(shù)怎么表達(dá)
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
 - 04-02c語言沒有round函數(shù) round c語言
 - 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計-用棧實現(xiàn)表達(dá)式求值的方法詳解
 - 01-10深入理解C++中常見的關(guān)鍵字含義
 - 01-10使用C++實現(xiàn)全排列算法的方法詳解
 - 01-10c++中inline的用法分析
 - 01-10深入理解鏈表的各類操作詳解
 - 01-10用C++實現(xiàn)DBSCAN聚類算法
 


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
 - 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
 - 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段
 - 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
 - 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
 - 04-02c語言沒有round函數(shù) round c語言
 - 04-02c語言分段函數(shù)怎么求 用c語言求分段
 - 04-02C語言中怎么打出三角函數(shù) c語言中怎
 - 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
 
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
 - 04-02jquery與jsp,用jquery
 - 01-10delphi制作wav文件的方法
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 - 01-10使用C語言求解撲克牌的順子及n個骰子
 - 01-10C#中split用法實例總結(jié)
 - 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 01-11ajax實現(xiàn)頁面的局部加載
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 - 08-05織夢dedecms什么時候用欄目交叉功能?
 


