单链表之数据结构

 

//-------程序功能说明: 本程序是一个单链表程序,

//-------能实现单链表的 创建、插入、删除、输出、求结点总数、修改。

//-------希望大家多提意见。。谢谢。。

     

             - - - -- - - -- - - -  程  序  刚  开  始  运  行  时  的  界  面 - - - - - - - --  --  -  

                

 

这是一个 Source file.....

 1  // 单链表.cpp : Defines the entry point for the console application.
 2  //=========================================好像有点明白了,在一个函数中 return  和  cout  的区别了。。
 3  
 4  //#include "stdafx.h"
 5  #include<iostream>
 6  //#include<stdio.h>
 7  #include<iomanip>
 8  using namespace std;
 9  
10  #define Times        150   //能输入命令的次数。主要是防止错误的命令输入。比如说,字符的输入。
11  #define MAXSIZE      100   //单链表最大的结点数。
12  #define NULL         0
13  #define TRUE         1
14  #define FALSE        0
15  #define OK           1
16  #define ERROR        0
17  #define INFEASIBLE  -1
18  #define OVERFLOW    -2
19  
20  typedef int Status;
21  typedef int ElemType;
22  
23  typedef struct LNode
24  {
25   ElemType data;
26   LNode    *next;
27  }LNode , *LinkList;

 

//class HeLiang_List 的 定义
 1  class HeLiang_List
 2  { 
 3  public:
 4  
 5   Status  Tail_CreatList_L(LinkList  &L,  int i);                //------------------尾擦法建立单链线性链表。。。。。。
 6   //顺位序输入 n 个元素的值,建立带头结点的单链线性表 L
 7  
 8  
 9   Status ListInsert_L(LinkList &L,  int i , ElemType  e);    //-------------------插入。。。。。。。
10   //在单链表 L 中第 i 个位置之前插入元素 e
11  
12   Status ListDele_L(LinkList  &L,  int i,  ElemType &e);      //------------------删除。。。。。。。
13   //带头结点的单链表线性表 L 中,删除第 i 个元素,并由 e 返回其值
14  
15   Status Change_L(LinkList &L, int i ,ElemType e);            //------------------修改。。。。。。。
16   //找到单链线性表 L 中,第 i 个位置,用 e 替换该位置原来的值。
17  
18   Status Count_L(LinkList L,   int i);                        //------------------计数。。。。。。。
19   //记录单链线性表 L 中结点个数。(头结点不包括在内)
20  
21   int Show_L(LinkList L);                                    //------------------输出。。。。。。。
22   //输出单链线性表 L 中的所有元素。
23   
24   Status Search_L(LinkList L,int i,ElemType e);            //--------------------查找。。。。。
25   //在线性链表中查找元素 e 。如果存在,则输出该元素在线性链表中的结点位置。否则,输出相应的信息提示。。
26  
27   void Suggest();
28   //  给出的建议。防止错误的输入。
29   
30  
31   void Useful_information();
32   //  给出相关信息提示。使程序运行界面更友好。
33   
34   
35   
36   void josephus_list(LinkList *e);                             //----------单链表--实际应用------求解==约瑟夫问题。
37   //求解约瑟夫问题。这是一个应用。。书上找到。。。。
38  
39  
40  private:
41   Status GetElem_L(LinkList L,  int i,  ElemType &e);         //------------------得到某个位置的元素值。。。。。。。
42   //L为带头结点的单链表的头指针。
43   //当第 i 个元素存在时,其值付给 e
44   //定义为私有成员。防止其他类中成员访问。。。实现信息的封装。我是这样理解的。。。。
45  
46  
47  }linklist ;

 

//Show_L(LinkList L)
 1 //======================================================================================================================
 2  
 3  int HeLiang_List::Show_L(LinkList L)
 4  { //输出单链线性表 L 中的所有元素。
 5   ElemType e;
 6   int j,m;        //变量有点儿多。。感觉有点儿乱。。。每个变量的生存周期都要考虑。。。。
 7   j=linklist.Count_L(L,m);
 8  // n=linklist.GetElem_L(L,i,e);
 9   if(j==0)
10    return ERROR;   //如果单链表中没有元素,返回 ERROR 不输出任何值。
11   else
12   {
13    cout<<"        The elems of  this  linklist  are : "<<endl<<"      ";
14    for(int i=1;i<=j;i++)
15    {
16     linklist.GetElem_L(L,i,e);            // 调用私有函数,输出链表中各节点的元素值。
17     if(i%10==0)  cout<<endl<<"      ";    // 格式控制的。。。前面已经定义了 #include <iomanip> 头文件。
18    }
19   }
20  cout<<endl;
21  return 0;
22  }//--------------Show_L

 

//Count_L(LinkList L, int m)
 1  Status HeLiang_List::Count_L(LinkList L,   int m)
 2  {         
 3   //记录单链线性表 L 中结点个数。(头结点不包括在内)
 4   m=0;     //  m  用来记录结点个数。
 5   LinkList p;  p=L;
 6  
 7   if(L->next==NULL)  return ERROR;  // 如果结点个数为 0 ,结束操作。不输出任何值。
 8   while(p->next!=NULL)
 9   {
10    ++m;
11     p=p->next ;
12   };
13   return m;      //  没有用 cout 直接来输出 m  的值。************** 因为其他函数会调用 count 函数,所以,用 return m; 语句要好些。。
14  }//----------------Count_L

 

//GetElem_L(LinkList L, int i, ElemType &e)
 1  Status HeLiang_List::GetElem_L(LinkList L,  int i,  ElemType &e)
 2  {      
 3   //L为带头结点的单链表的头指针。
 4   //当第 i 个元素存在时,其值付给 e 并返回 OK ,否则返回  ERROR
 5   LinkList p;
 6   p = L->next;
 7   int j = 1;           // 初始化,p指向第一个结点,j为计数器
 8   while (p && j<i)
 9   {   // 顺指针向后查找,直到p指向第i个元素或p为空
10    p = p->next;  ++j;
11   }
12   if ( !p || j>i ) return ERROR;  // 第i个元素不存在
13   e = p->data;   // 取第i个元素
14   cout<<setiosflags(ios::left)<<setw(10)<<e<<"  ";//格式化输出。。参见课本 P53 页。
15   return OK;
16  }//----------------GetElem_L

 

//Tail_CreatList_L(LinkList &L, int n)
 1  Status HeLiang_List::Tail_CreatList_L(LinkList  &L,  int n)
 2  {
 3   //尾擦法。顺位序输入 n 个元素的值,建立带头结点的单链线性表 L
 4   LinkList  p,q;
 5   L=(LinkList)malloc(sizeof(LNode));//--------------------------------在编程时,我掉了。。。花了我一天时间去找错误。可叹。。
 6   L->next=NULL;//建立一个带头结点的单链表
 7      q=L;
 8   cout<<"        The elem type of this linklist is int . Please initiate  the linklist . "<<endl;
 9   cout<<"        If you want to quit,   remember to input  0 .  "<<endl;
10   cout<<"                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"<<endl;
11   cout<<"        Now ! Please input the elems of the linklist :  ";
12   for(int i=1;i<=MAXSIZE;i++)
13   {
14    p=(LinkList)malloc(sizeof(LNode));      // 分配 基地址给 p 。理解的不是很深刻。。。有待进一步提高。。
15    cin>>p->data;
16    if(i==1&&p->data ==0)
17    {
18     cout<<"----------  The initialization of the linklist is failed . "<<endl;
19     break;     //  这行代码就不解释了吧。。。
20    }
21    if(p->data==0)
22     break;     // 当输入 0 时,表示链表初始化完成。结束循环。
23    q->next=p;     // 将指针指向链表下一个结点。
24    q=p;           // 指向下一个结点。
25   }
26   q->next=NULL;      // 循环结束后,将最后一个结点指空。
27   if(L->next==NULL)  // 当输入 0 时,L 链表的 next 指向空。
28    return 0;      // 此时,结束程序。
29   return OK;     // 初始化成功,正常结束程序。
30  }//////////////-------Tail_CreatList_L

 

//ListInsert_L(LinkList &L, int i , ElemType e)
 1  Status HeLiang_List::ListInsert_L(LinkList &L,  int i , ElemType  e)
 2  {
 3   //在单链表 L 中第 i 个位置之前插入元素 e
 4   LinkList s,p;
 5   p=L;
 6   int  k,j=0;      //  定义了许多变量。。哎。。不太适应。。。
 7   k=linklist.Count_L(L,i)+1;  // 插入的位置,不能大于 k 的值。
 8   cout<<"        Please input the position where you want to Insert a elem :  ";
 9   cin>>i;
10   if(i<=0||i>k)   //  判断输入的位置是否合法。
11   {cout<<"        Are      you    joking   ???   You input the wrong position . "<<endl;
12   return ERROR;  //  如果输入位置不合法,结束程序,并返回 ERROR 。
13   }
14   else
15   {
16    cout<<"        Please input the elem which  you want to insert it in the linklist :  ";
17    cin>>e;        // 输入要插入的元素的值。
18    while(j<i-1){p=p->next;++j;}  // 一般情况下是 j=i的时候,结束了循环。找到地 i 个结点。因为前面已经判断了输入位置的合法性了。
19    s=(LinkList)malloc(sizeof(LNode)); // 找到了第 i-1 个结点的位置。
20    s->data=e;
21    s->next=p->next;         // 执行插入操作。
22    p->next=s;  
23   }
24   return OK;
25  }////////////------ListInsert_L

 

//ListDele_L(LinkList &L, int i, ElemType &e)
 1  Status HeLiang_List::ListDele_L(LinkList  &L,  int i,  ElemType &e) 
 2  { //带头结点的单链表线性表 L 中,删除第 i 个元素
 3   int k=linklist.Count_L(L,i);
 4   cout<<"        Please input the position where you want to Delete the elem :  ";
 5   cin>>i;
 6   if(i>k||i<=0)
 7   {
 8    cout<<"        You input the wrong position .  "<<endl;
 9    return ERROR;
10   }
11   else
12   {
13    LinkList p,q;
14    p = L;
15    int j = 0;
16    while (j < i-1) //这里是小于 i-1  的。。。
17    {
18     // 寻找第i个结点,并令p指向其前趋
19     p = p->next; 
20     ++j;
21    }  
22    q = p->next;                 // p 是要删除的结点的前面一个结点。。。。
23    p->next = q->next;           // 删除并释放结点
24    e = q->data;
25    cout<<"        The LNode of position "<<i<<" has been deleted."<<" The elem which has been deleled is "<<e<<endl;
26    free(q);
27   }
28  
29   return OK;
30  }//------------------ListDelelte_L

 

//Change_L(LinkList &L, int i ,ElemType e)
 1  Status HeLiang_List::Change_L(LinkList &L, int i ,ElemType e)
 2  {
 3   //找到单链线性表 L 中,第 i 个位置,用 e 替换该位置原来的值。
 4   int j,k;
 5   LinkList p;
 6   p=L;   
 7   k=linklist.Count_L(L,i);   //  count 函数用了很多次。。
 8   cout<<"        Please input the position where you want to Change the elem : ";
 9   cin>>i;
10   if(i<0||i>k)    //   判断。。。不想过多的解释。。。
11   {cout<<"        Are   you  joking ???   You input the wrong position . "<<endl;
12   return ERROR; 
13   }
14   else
15   {
16    cout<<"        Please input the new elem in this position :  ";
17    cin>>e;
18    for( j=1;j<=i;j++)
19    {
20     p=p->next ;  
21    }
22    p->data=e;     //  p 为第 i 个位置的结点。将 e 作为该结点的新的元素。
23   }
24   return OK;
25  }

 

//Search_L(LinkList L,int i,ElemType e)
 1  Status HeLiang_List::Search_L(LinkList L,int  i,ElemType e)
 2  {
 3   //输入元素 e 。如果在链表中找到,则返回第一个找到的位置。
 4  
 5   int j,k;
 6   k=linklist.Count_L(L,i);
 7   cout<<"        Please input the elem that you want to Search  :";
 8   cin>>e;
 9   for( j=1;j<=k;j++)
10   {
11    L=L->next ;
12    if(L->data!=e)
13     continue ;     //  如果要找的元素和L->data 不相等,继续往下找。
14    if(L->data ==e)   //  找到了第一个与元素 e 相等的结点。
15    {
16     cout<<"        Congratulations!"<<endl;
17     cout<<"        The first position of the elem“"<<e<<"” in this linklist  is  "<<j<<" ."<<endl;
18     break;
19    }
20   }
21   if(j>k)    //   遍历了整个链表,没找到与元素 e 相同的元素。说明, e 不再链表中。
22    cout<<"        Sorry !  The elem "<<e<<" can't be found in this linklist. ";
23   cout<<endl;
24  
25  return 0;
26  }

 

 1  void HeLiang_List::Useful_information()   // 相关的信息提示,使运行界面更加友好。
 2  {
 3   cout<<"*********************************************************************************************"<<endl;
 4   cout<<"                           Useful      Information    "<<endl;
 5   cout<<"                       Function          Command"<<endl;
 6   cout<<"                        Exit                0  "<<endl;
 7   cout<<"                        Initialization      1  "<<endl;
 8   cout<<"                        Show                2  "<<endl;
 9   cout<<"                        Insert              3  "<<endl;
10   cout<<"                        Delete              4  "<<endl;
11   cout<<"                        Change              5  "<<endl;
12   cout<<"                        Search              6  "<<endl;
13   cout<<"                        Count               7  "<<endl;
14   cout<<"                        Help                8  "<<endl;
15   cout<<"                        Application         9  "<<endl;
16   
17   cout<<"*********************************************************************************************"<<endl<<endl;
18  }

 

//Suggest()
1  void HeLiang_List::Suggest()   //  自己的一些建议,使程序能正确的输入。。少犯点儿错误。。。
2  {
3   cout<<"########                                                                             ########"<<endl;
4   cout<<"######## I strongly  suggest  you that you should initialize  the linklist  first.   ########"<<endl;
5   cout<<"########                                                                             ########"<<endl<<endl;
6  }

 

//int main
 1  int main()
 2  {
 3   LinkList  L;
 4   //用 LinkList 指针类型,定义一个 指向 LNode 类型的 指针变量 L .
 5   //这个程序只能对一个 linklist 类的链表进行操作。。无法实现多个 linklist 的操作。
 6   //例如,如果先定义 一个 La 链表,再定义一个 Lb 链表。输出时,只能输出 Lb 链表中的元素。 La 则消失了。。我也不是很清楚耶。。
 7   int command;
 8   ElemType e;
 9   int i,n,k,quit=0;      //  有时候,定义的变量多了,感觉有点驾驭不了。。。。。。。。
10  
11   linklist.Useful_information();  //  首先给出相关函数的信息提示。。
12   linklist.Suggest();             //  写成函数了。尽量让主函数看起来简洁、清晰。
13   do      // 直型循环。可以多次操作。。。
14   {
15    quit+=1;
16    if(quit>Times)
17    //如果错误的输入了除整型以外的其他字符作为命令,则在循环了 Times 次之后,结束程序。(如果不写这个语句,程序会不停地循环下去。)
18    //当然,times  是一个比较大的整数。前面已经用宏定义了。。。
19    {
20     cout<<endl<<endl<<"        Sorry !!!    You must carefully  read the Useful Iformation   first ........   "<<endl<<endl;
21     break;
22    }
23    cout<<"-----Please input the command :" ;   // 给出相关的信息提示。
24    cin>>command;
25    switch(command)  //  多选择分支函数。根据不同的输入命令,执行不同的函数。
26    {
27  
28    case 0:      // 如果输入命令 0 ,结束程序。
29     break;  
30  
31    case 1:      // 如果输入命令 1 ,执行初始化操作。
32     cout<<"    everything is ok..... "<<endl;
33     linklist.Tail_CreatList_L(L,n);
34     linklist.Show_L(L);
35     break;
36  
37    case 2:      // 如果输入命令 2 ,输出链表中所有元素。
38     linklist.Show_L(L);   
39     break;
40  
41    case 3:      // 如果输入命令 3 ,在第 i 个元素之前,插入新的结点,并给该结点赋值。
42     linklist.ListInsert_L(L,i,e);
43     break;
44  
45    case 4:      // 如果输入命令 4 ,链表中第 i 个结点。
46     linklist.ListDele_L(L,i,e);
47     break;
48  
49    case 5:      // 如果输入命令 5 ,改变链表中第 i 结点的元素的值。
50     linklist.Change_L(L,i,e);
51     break;
52  
53    case 6:      // 如果输入命令 6 ,在链表中查找第 i 个结点。如果存在,则返回该结点的元素 e 。否则,给出相应信息提示。
54     linklist.Search_L(L,i,e);
55     break;
56  
57  
58    case 7:      // 如果输入命令 7 ,计算链表中节点的个数。
59     k=linklist.Count_L(L,i);
60     cout<<"        The  count  of  this  LNode  is  "<<k<<endl;
61     break;
62     
63    case 8:      // 如果输入命令 8 ,给出帮助信息。
64     linklist.Useful_information();
65     break;
66  
67  
68    default :      // 如果输入了错误的命令,给出相应提示。。
69     cout<<"^^^^^^^^^^^^^^^  You input the wrong command.  If  you  need help,  please  input  8     ^^^^^^^^^^^^^ "<<endl;
70     break;
71    }
72   }
73   while(command != 0);   //  写程序的时候,是对个人综合知识的考察。。。
74   cout<<endl<<"############-----Nothing is best.   But everything can be better.  Just do it!-----############  "<<endl;
75  
76   
77  /* cout<<endl<<"-----------   Press  “Enter” key  to continue.  ";
78   getchar();
79   putchar(getchar());
80  */
81  
82  
83   return 0;
84  }

 

 

 

 

////////////- - - - - - -  - -- - - - - - - - 初 始 化 时 的 界 面 - - - - - - - - - - - - -- - - - - -

                 

 

                      - - - - - - - - - - - - - - 退   出   程   序   时   的   界   面 - - - - - - - - - - - - - - - -

                 

posted @ 2011-05-26 08:06  He_LiangLiang  阅读(1844)  评论(6编辑  收藏  举报