单链表之数据结构
//-------程序功能说明: 本程序是一个单链表程序,
//-------能实现单链表的 创建、插入、删除、输出、求结点总数、修改。
//-------希望大家多提意见。。谢谢。。
- - - -- - - -- - - - 程 序 刚 开 始 运 行 时 的 界 面 - - - - - - - -- -- -
这是一个 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 }
////////////- - - - - - - - -- - - - - - - - 初 始 化 时 的 界 面 - - - - - - - - - - - - -- - - - - -
- - - - - - - - - - - - - - 退 出 程 序 时 的 界 面 - - - - - - - - - - - - - - - -