zoukankan      html  css  js  c++  java
  • VC++2012编程演练数据结构《15》双循环链表

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

    打开IDE 

    我们来创建一个工程实践之


    类的声名如下


    #if !defined(AFX_DCIRLINKL_H__4D93E797_B8BC_4781_BD9A_0EF8A6458A75__INCLUDED_)
    #define AFX_DCIRLINKL_H__4D93E797_B8BC_4781_BD9A_0EF8A6458A75__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    //双向循环链表的类定义
    typedef int ElemType;
    //双向链表结点的类型定义
    typedef struct DuLNode {
      ElemType  data;
      struct DuLNode *prior;//左指针
      struct DuLNode *next;//右指针
    }DuLNode;
    #define LEN 20
    
    class DuLinkList
    {private:
    DuLNode *head;//指向表头的指针
    DuLNode *curr;//当前结点指针
    int count;// 双向循环链表的结点个数
    public:
    	//构造函数
    	DuLinkList();
    	//析构函数
    	~DuLinkList(){delete head;}
    	//创建有序或无序的带头结点的双向循环链表
    	DuLNode *CreateCLinkL(int,int,int mark=0);
    	//清空单循环链表
    	void ClearCList();
    	//求双向循环链表长度
    	int CListSize();
    	//检查双向循环链表是否为空
    	bool CListEmpty();
    	//返回指向第pos个结点的指针
    	DuLNode *Index(int pos);
    	//返回双向循环链表中指定序号的结点值
    	ElemType GetElem(int pos);
    	//遍历双向循环链表
    	void TraverseCList();
    	//当前指针curr指向pos结点并返回curr
    	DuLNode *Reset(int pos=0);
    	//当前指针curr指向下一结点并返回
    	DuLNode *Next();
    	//当前指针curr指向上一结点并返回
    	DuLNode *Prior();
    	// 判双向循环链表当前指针curr==head 否
    	bool EndOCList();
    	//判双向循环链表当前指针curr->next是否到达表尾
    	bool EndCList();
    	//判双向循环链表当前指针curr->prior是否到达表尾
    	bool PEndCList();
    	//删除curr->next所指结点,并返回所删结点的data
    	ElemType DeleteNt();
    	//从双向循环链表中查找元素
    	bool FindCList(ElemType& item);
    	//更新双向循环链表中的给定元素
    	bool UpdateCList(const ElemType &item,ElemType &e);
    	//向链表中第pos个结点前插入域值为item的新结点
    	void InsertCLfront(const ElemType& item,int pos);
    	//向链表中第pos个结点后插入域值为item的新结点
    	void InsertCLafter(const ElemType& item,int pos);
    	//从链表中删除第pos个结点并返回被删结点的data
    	ElemType DeleteCList(int pos);
    };
    
    #endif // !defined(AFX_DCIRLINKL_H__4D93E797_B8BC_4781_BD9A_0EF8A6458A75__INCLUDED_)
    


    类的实现如下

    #include "stdafx.h"
    #include "dcirlinkl.h"
    
    //双向循环链表的实现
    #include<iostream>
    #include<stdlib.h>
    
    //构造函数
    DuLinkList::DuLinkList()
    {head=new DuLNode;
     head->prior=head;
     head->next=head;
     curr=NULL;
     count=0;
    }
    //创建有序或无序的带头结点的双向循环链表
    DuLNode *DuLinkList::CreateCLinkL(int n,int m,int mark)
    {ElemType x,a[LEN];
     srand(m);
     for(int i=0;i<n;i++) a[i]=rand()%100;
     for(int i=0;i<n-1;i++)
      {int k=i;
       for(int j=i+1;j<n;j++)
        if(a[k]>a[j]) k=j;
       if(k!=i)
       {x=a[k];a[k]=a[i];a[i]=x;}}
     DuLNode *p;
     head=new DuLNode;
     head->prior=NULL;
     head->next=curr=p=new DuLNode;
     curr->prior=head;
     for(int i=0;i<n;i++){
      if(mark==1) p->data=a[i];//升序
      else
       if(mark==-1) p->data=a[n-1-i];//降序
       else p->data=rand()%100;//无序
      if(i<n-1){curr=curr->next=new DuLNode;
       curr->prior=p;p=curr;}
      count++;}
     head->prior=curr;
     curr->next=head;
     return head;
    }
    //清空双向循环链表
    void DuLinkList::ClearCList()
    {DuLNode *cp,*np;
     cp=head->next;
     while(cp!=head)
     {np=cp->next;delete cp;cp=np;}
     head=NULL;
    }
    //求双向循环链表长度
    int DuLinkList::CListSize()
    {DuLNode* p=head->next;
     int i=0;
     while(p!=head)
      {i++;p=p->next;}
     return i;
    }
    //检查双向循环链表是否为空
    bool DuLinkList::CListEmpty()
    {return head->next==head;}
    //返回指向第pos个结点的指针
    DuLNode *DuLinkList::Index(int pos)
    {if(pos<1)
      {cerr<<"pos is out range!"<<endl;exit(1);}
     DuLNode* p=head->next;
     int i=0;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;}
     if(p!=head) return p;
     else {cerr<<"pos is out range!"<<endl;
      return NULL;}
    }
    //返回双向循环链表中指定序号的结点值
    ElemType DuLinkList::GetElem(int pos)
    {if(pos<1)
     {cerr<<"pos is out range!"<<endl;exit(1);}
     DuLNode* p=head->next;
     int i=0;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;}
     if(p!=head) return p->data;
     else {cerr<<"pos is out range!"<<endl;
      return pos;}
    }
    //遍历双向循环链表
    void DuLinkList::TraverseCList()
    {DuLNode *p=head->next;
     while(p!=head)
      {cout<<setw(4)<<p->data;
       p=p->next;}
     cout<<endl;
    }
    //当前指针curr指向pos结点并返回curr
    DuLNode *DuLinkList::Reset(int pos)
    {DuLNode* p=curr=head->next;
     int i=-1;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;curr=curr->next;}
     return curr;
    }
    //当前指针curr指向下一结点并返回
    DuLNode *DuLinkList::Next()
    {curr=curr->next;
     return curr; 
    }
    //当前指针curr指向上一结点并返回
    DuLNode *DuLinkList::Prior()
    {curr=curr->prior;
     return curr;
    }
    // 判双向循环链表当前指针curr==head 否
    bool DuLinkList::EndOCList()
    {return curr==head;}
    //判双向循环链表当前指针curr->next是否到达表尾
    bool DuLinkList::EndCList()
    {return curr->next==head;}
    //判双向循环链表当前指针curr->prior是否到达表尾
    bool DuLinkList::PEndCList()
    {return curr->prior==head;}
    //删除curr->next所指结点,并返回所删结点的data
    ElemType DuLinkList::DeleteNt()
    {DuLNode *p=curr->next;
     curr->next=p->next;
     curr->next->next->prior=p->prior;
     ElemType data=p->data;
     delete p;
     count--;
     return data;
    }
    //从双向循环链表中查找元素
    bool DuLinkList::FindCList(ElemType& item)
    {DuLNode* p=head->next;
     while(p!=head)
      if(p->data==item)
       {item=p->data;return true;}
      else p=p->next;
     return false;
    }
    //更新双向循环链表中的给定元素
    bool DuLinkList::UpdateCList(const ElemType &item,ElemType &e)
    {DuLNode* p=head->next;
     while(p!=head)  //查找元素
      if(p->data==item) break;
      else p=p->next;
     if(p==head) return false;
     else {  //更新元素
      p->data=e;return true;}
    }
    //向链表中第pos个结点前插入域值为item的新结点
    void DuLinkList::InsertCLfront(const ElemType& item,int pos)
    {DuLNode *newP=new DuLNode;
     newP->data=item;
     DuLNode* p=head->next;
     int i=0;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;}
     newP->prior=p->prior;
     p->prior->next=newP;
     newP->next=p;
     p->prior=newP;
     count++;
    }
    //向链表中第pos个结点后插入域值为item的新结点
    void DuLinkList::InsertCLafter(const ElemType& item,int pos)
    {DuLNode *newP=new DuLNode;
     newP->data=item;
     DuLNode* p=head->next;
     int i=-1;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;}
     newP->prior=p->prior;
     p->prior->next=newP;
     newP->next=p;
     p->prior=newP;
     count++;
    }
    //从链表中删除第pos个结点并返回被删结点的data
    ElemType DuLinkList::DeleteCList(int pos)
    {if(pos<1)
      {cerr<<"pos is out range!"<<endl;exit(1);}
     DuLNode *p=head->next;
     ElemType data;
     int i=0;
     while(p!=head)
      {i++;
       if(i==pos) break;
       p=p->next;}
     if(p!=head)
      {data=p->data;
       p->prior->next=p->next;
       p->next->prior=p->prior;
       delete []p;count--;return data;}
     else return pos;  
    }
    



    调用如下

    #include "stdafx.h"
    
    #include "dcirlinkl.h"
    void main()
    {
    cout<<"运行结果:\n";
    int m=150,i,n=10,x,it;
    DuLinkList p,t,q,mylink;
    p.CreateCLinkL(n,m,1);
    if(p.CListEmpty()) cout<<"双向循环链表p空!\n";
    else cout<<"双向循环链表p非空!\n";
    cout<<"双向循环链表p(升序):\n";
    p.TraverseCList();
    if(p.CListEmpty()) cout<<"双向循环链表p空!\n";
    else cout<<"双向循环链表p非空!\n";
    if(p.EndCList()) cout<<"双向循环链表p满!\n";
    else cout<<"双向循环链表p非满!\n";
    cout<<"双向循环链表t(无序):\n";
    t.CreateCLinkL(n-2,m);
    t.TraverseCList();
    cout<<"双向循环链表t的长度:"<<t.CListSize()<<endl;
    cout<<"双向循环链表q(降序):\n";
    q.CreateCLinkL(n,m,-1);
    q.TraverseCList();
    cout<<"双向循环链表q的长度:"<<q.CListSize()<<endl;
    cout<<"链表q的第1个元素:"<<q.GetElem(1)<<endl;
    cout<<"链表q的第1个元素地址:"<<q.Index(1)<<endl;
    cout<<"链表q的第5个元素:"<<q.GetElem(5)<<endl;
    cout<<"链表q的第5个元素地址:"<<q.Index(5)<<endl;
    cout<<"链表q的第10个元素:"<<q.GetElem(10)<<endl;
    cout<<"链表q的第10个元素地址:"<<q.Index(10)<<endl;
    cout<<"链表q的curr->next所指元素地址:"<<q.Next()<<endl;
    x=65;it=66;
    if(q.FindCList(x)) cout<<x<<"查找成功!\n";
    else cout<<x<<"查找不成功!\n";
    if(q.UpdateCList(x,it)) cout<<x<<"更新成功!\n";
    else cout<<x<<"更新不成功!\n";
    cout<<"更新后双向循环链表q:\n";
    q.TraverseCList();
    cout<<"插入后双向循环链表q:\n";
    it=100;q.InsertCLfront(it,1);
    q.TraverseCList();
    cout<<"插入后双向循环链表q:\n";
    it=101;q.InsertCLfront(it,5);
    q.TraverseCList();
    cout<<"插入后双向循环链表q:\n";
    it=102;q.InsertCLfront(it,13);
    q.TraverseCList();
    cout<<"插入后q表长:"<<q.CListSize()<<endl;
    cout<<"第1个数:"<<q.DeleteCList(1)<<"删除成功!\n";
    cout<<"删除后q表长:"<<q.CListSize()<<endl;
    q.TraverseCList();
    cout<<"第5个数:"<<q.DeleteCList(5)<<"删除成功!\n";
    cout<<"删除后q表长:"<<q.CListSize()<<endl;
    q.TraverseCList();
    cout<<"第11个数:"<<q.DeleteCList(11)<<"删除成功!\n";
    cout<<"删除后q表长:"<<q.CListSize()<<endl;
    q.TraverseCList();
    cout<<"删除的数为:"<<q.DeleteNt()<<endl;
    cout<<"删除后q表长:"<<q.CListSize()<<endl;
    q.TraverseCList();
    cout<<"求解约瑟夫(Josephus)问题\n";
    cout<<"输入人数n:";cin>>n;
    cout<<"输入第次数m:";cin>>m;
    for(i=0;i<n;i++) mylink.InsertCLafter(i+1,i);
    cout<<"员工编号依次为:";
    DuLNode *w=mylink.Reset();
    while(!mylink.EndOCList())
    {cout<<setw(3)<<w->data;
    w=mylink.Next();}
    cout<<endl;
    cout<<"删除次序依次为:\n";
    mylink.Reset(-1);
    for(i=0;i<n-1;i++)
    {for(int j=0;j<m-1;j++)
    {w=mylink.Next();
    if(mylink.EndOCList()) w=mylink.Next();}
    if(mylink.EndCList()) w=mylink.Next();
    cout<<"删除第"<<mylink.DeleteNt()<<"人\n";}
    cout<<"最后剩下的是:第"<<mylink.GetElem(1)<<"个人\n";
     cin.get();cin.get();
    }



    效果如下



    代码下载地址

    http://download.csdn.net/detail/yincheng01/4788352


  • 相关阅读:
    那些ubuntu创建用户踩过的坑
    Build tools
    version control(以git为例)讲解
    URI和URL的区别
    HTTP解析过程心得
    函数式编程(functional programming)
    cb45a_c++_STL_算法_删除_(3)_unique(唯一的意思)删除连续性的重复的数据
    cb44a_c++_STL_算法_删除_(2)remove_copy_remove_copy_if
    cb43a_c++_STL_算法_删除_(1)remove_remove_if
    cb42a_c++_STL_算法_替换_replace
  • 原文地址:https://www.cnblogs.com/new0801/p/6177652.html
Copyright © 2011-2022 走看看