1 #include<iostream> 2 using namespace std; 3 4 #define OK 1 5 #define ERROR 0 6 #define OVERFLOW -2 7 typedef int Status; //Status 是函數返回值類型,其值是函數結果狀態代碼。 8 typedef int ElemType; //ElemType 為可定義的數據類型,此設為int類型 9 10 typedef struct LNode 11 { 12 ElemType data; //結點的數據域 13 struct LNode *next; //結點的指針域 14 }LNode,*LinkList; //LinkList為指向結構體LNode的指針類型 15 16 17 Status InitList_L(LinkList &L){ //算法2.5 單鏈表的初始化 18 //構造一個空的單鏈表L 19 L=new LNode; //生成新結點作為頭結點,用頭指針L指向頭結點 20 L->next=NULL; //頭結點的指針域置空 21 return OK; 22 } 23 24 Status ListInsert_L(LinkList &L,int i,ElemType &e){ //算法2.8 單鏈表的插入 25 //在帶頭結點的單鏈表L中第i個位置之前插入元素e 26 int j; 27 LinkList p,s; 28 p=L;j=0; 29 while(p && j<i-1){p=p->next;++j;} //剛好指向第i-1個節點 30 if(!p||j>i-1) return ERROR; //i大於表長+1或者小於1 當p不為空時如果i小於1的話則插入失敗,如果p為空的話表明i大於表長 31 s=new LNode; //生成新結點s p指向當前第i-1的節點位置 32 s->data=e; //將結點s的數據域置為e 33 s->next=p->next; //將結點s插入L中 34 p->next=s; 35 return OK; 36 }//ListInsert_L 37 38 void CreateList_F(LinkList &L,int n){ //算法2.10 (前插法)創建單鏈表 39 //逆位序輸入n個元素的值,建立到頭結點的單鏈表L 40 LinkList p; 41 L=new LNode; 42 L->next=NULL; //先建立一個帶頭結點的空鏈表 43 cout<<"請輸入 "<<n<<" 個數(以空格隔開,按回車結束):"; 44 for(int i=n;i>0;--i){ 45 p=new LNode; //生成新結點 46 cin>>p->data; //輸入元素值 47 p->next=L->next; 48 L->next=p; //插入到表頭 49 } 50 }//CreateList_F 51 52 void CreateList_L(LinkList &L,int n){ //算法2.11 (后插法)創建單鏈表 53 //正位序輸入n個元素的值,建立到頭結點的單鏈表L 54 LinkList r,p; 55 L=new LNode; 56 L->next=NULL; //先建立一個帶頭結點的空鏈表 57 r=L; //尾指針r指向頭結點 58 cout<<"請輸入 "<<n<<" 個數(以空格隔開,按回車結束):"; 59 for(int i=0;i<n;i++){ 60 p=new LNode; //生成新結點 61 cin>>p->data; //輸入元素值 62 p->next=NULL; 63 r->next=p; //插入到表尾 64 r=p; //r指向新的尾結點 r始終指向當前節點 65 } 66 }//CreateList_L 67 68 Status findValList_L(LinkList L,int i,ElemType &indexVal){ //5.查找位序為i的元素,返回其值 69 LinkList p=L->next;//指向第一個結點 70 int j=1;//標記當前節點的位置為1 71 while(p && j<i){ //找第i個節點 72 p=p->next; //循環鏈表 73 ++j; //同步p節點的位置 74 } 75 if(!p||j>i)return ERROR; // i值不合法:!p表示i大於表長;j>i表示i小於1這種情況 76 indexVal=p->data;//把第i個節點的值賦值給indexVal 77 return OK; //返回1,表示查找成功 78 } 79 80 Status findIndexList_L(LinkList L,ElemType val,int &index){ //6.依值查找,返回其位序 81 LinkList p=L->next;//指向第一個節點 82 int j=1; //同時標記起始位置為1 83 while(p){ 84 if(p->data==val){ //依次比較 85 index=j; //如果相等的話就把當前p的位置 86 return OK; //返回1表示查找成功 87 } 88 p=p->next; //循環鏈表 89 j++; //同步p指針的位置 90 } 91 return ERROR; //前面沒有返回的話,這時返回失敗,表示找不到 92 } 93 94 Status deleteIndexList_L(LinkList &L,int i,ElemType &indexVal){ //7.刪除表中第i個元素 95 LinkList p=L; //這時要指向頭節點,因為當i=1時,下面的循環進不去,也就是if判斷不成功,這時進行刪除節點操作 96 int j=0; //同步p節點的位置 97 while(p && j<i-1){ //找到第i-1個節點 98 p=p->next; //循環鏈表 99 j++; //同步當前節點 100 } 101 if(!p||j>i-1)return ERROR; // !p表示i大於鏈表表長,j>i-1表示i小於1,此時p不為空 102 LinkList q=p->next; //q節點指向第i個節點 103 if(!q)return ERROR; //根據條件,此處應該判斷p的后繼是否為空即為i這個特殊情況,舉個例子,表長j為3時,i為4,到此句的時候就成立,表示表長加1這個位置沒有元素,返回刪除失敗 104 indexVal=q->data; 105 p->next=q->next; //鏈接鏈表 106 delete q; //刪除第i個節點 107 return OK; //表示刪除成功 108 } 109 110 Status findMaxList_L(LinkList L,int &index,int &MaxVal){ //8.返回值最大的元素及其在表中位置,引用最大值 111 if(L->next==NULL)return ERROR; //如果是空鏈表,則返回0 112 LinkList p=L->next->next; //將p指向第二個節點 113 int j=2; //同時同步指針位置 114 MaxVal=L->next->data; //標記第一個節點的值為最大值 115 index=1; //同步最大值的位置 116 while(p){ 117 if(p->data>MaxVal){ //當前p的數據與MaxVal比較 118 MaxVal=p->data; //賦值 119 index=j; //標記位置 120 } 121 p=p->next; //循環鏈表 122 j++; //同步p的位置 123 } 124 return OK; //表示查找成功 125 } 126 127 Status reverseList_L(LinkList &L){ //9.就地逆置算法 128 LinkList p=L->next,q; //先用p來保存原來的第一個節點 129 L->next=NULL; //仍利用原鏈表的首地址,此時將頭結點指向空 130 if(!p)return ERROR; //如果第一個節點為空,則為空表 131 while(p){ 132 q=p->next; //先用q來保存p節點的next域,用來移動原來的鏈表 133 p->next=L->next; //仍用L空間,每次插在頭結點后面的位置 134 L->next=p; //L(帶頭節點)時刻指向當前節點p 135 p=q; //將p重新指向原表中p的后繼 136 } 137 return OK; //表示逆序成功 138 } 139 140 Status delItemList_L(LinkList &L,ElemType item){ //10.刪除表中所有值為item的數據元素 141 LinkList p=L,q; //指向頭節點,臨時指針q 142 bool f=false; //標記鏈表中是否有item這個元素 143 while(p){ 144 if((q=p->next)&&(q->data==item)){ //先判斷是否有這個p->next這個元素 145 if(!f)f=true;//有的話只標記一次就好 146 p->next=q->next; //鏈接鏈表 147 delete q; 148 } 149 else p=p->next;//否則才移動p 150 } 151 if(!f)return ERROR; //標記該表中沒有此元素 152 return OK; 153 } 154 155 Status delMinList_L(LinkList &L,int &indexMin,ElemType &minVal){ //11.實現刪除單鏈表中值最小的數據元素 156 LinkList p=L->next; 157 if(!p)return ERROR; //空表 158 minVal=p->data; //標記第一個節點為最小值 159 indexMin=1; //同步最小值節點位序 160 p=p->next; //指向第二個節點 161 int j=2; //同步p節點的位序 162 while(p){ //先去找最小值 163 if(p->data<minVal){ //依次比較 164 minVal=p->data; 165 indexMin=j; 166 } 167 p=p->next; //循環鏈表 168 j++; 169 } 170 LinkList q=L,tmp; 171 for(int i=1;i<indexMin;i++) //找到要刪除節點的前驅 172 q=q->next; 173 tmp=q->next; //保存要刪除的節點 174 q->next=tmp->next; //鏈接鏈表 175 delete tmp; // 刪除節點 176 return OK; //刪除成功 177 } 178 int main() 179 { 180 int i,n,choose; 181 ElemType x; 182 LinkList L,p; 183 184 choose=-1; 185 while(choose!=0) 186 { 187 cout<<"******************************************************************************\n"; 188 cout<<" 1. 建立空鏈表; 2. 在表中輸入指定個數的數據元素\n"; 189 cout<<" 3. 在第i個元素的前插入一個元素; 4. 逐個顯示表中數據元素\n"; 190 cout<<" 5. 查找位序為i的元素,返回其值; 6. 依值查找,返回其位序\n"; 191 cout<<" 7. 刪除表中第i個元素; 8. 返回值最大的元素及其在表中位置\n"; 192 cout<<" 9. 就地逆置; 10. 刪除表中所有值為item的數據元素\n"; 193 cout<<" 11.刪除單鏈表中值最小的數據元素; 0. 退出\n"; 194 cout<<"*******************************************************************************\n"; 195 196 cout<<"請選擇:"; 197 cin>>choose; 198 switch(choose) 199 { 200 case 1: //建立一個單鏈表 201 if(InitList_L(L)) 202 cout<<"成功建立鏈表!\n\n"; 203 break; 204 case 2: //使用后插法創建單鏈表 205 cout<<"請輸入一個數,代表元素的個數:"; 206 cin>>n; 207 CreateList_L(L,n); 208 cout<<"成功創建鏈表!\n\n"; 209 break; 210 case 3: //單鏈表的插入 211 cout<<"請輸入兩個數,分別代表插入的位置和插入數值(用空格間隔,最后回車):"; 212 cin>>i>>x; //輸入i和x,i代表插入的位置,x代表插入的數值 213 if(ListInsert_L(L,i,x)) 214 cout<<"成功將"<<x<<"插在第"<<i<<"個位置\n\n"; 215 else 216 cout<<"插入失敗!\n\n"; 217 break; 218 case 4: //單鏈表的輸出 219 p=L->next;//指向第一個節點 220 if(!p) 221 cout<<"當前為空鏈表"<<endl<<endl; 222 else{ 223 cout<<"現在鏈表里的數分別是:"; 224 i=0; 225 while(p){//循環直到為空 226 i++; 227 cout<<p->data<<","; 228 p=p->next; 229 } 230 cout<<"共有"<<i<<"個元素。"<<endl<<endl; 231 } 232 break; 233 case 5: //查找位序為i的元素,返回其值 234 cout<<"請輸入一個你想要查找該元素的位序:"; 235 cin>>i; 236 if(findValList_L(L,i,x)) 237 cout<<"位序為"<<i<<"的元素為"<<x<<".\n"<<endl; 238 else 239 cout<<"輸入位序序號不在鏈表節點序號范圍內"<<endl<<endl; 240 break; 241 case 6: //依值查找,返回其位序 242 int index; 243 cout<<"請輸入要查找的元素:"; 244 cin>>x; 245 if(findIndexList_L(L,x,index)) 246 cout<<"查找元素"<<x<<"在鏈表中的位序為"<<index<<".\n"<<endl; 247 else 248 cout<<"此元素不在該鏈表中"<<endl<<endl; 249 break; 250 case 7: //刪除表中第i個元素 251 cout<<"請輸入刪除表中元素的位置:"; 252 cin>>i; 253 if(deleteIndexList_L(L,i,x)) 254 cout<<"第"<<i<<"個位置的元素"<<x<<"已被刪除.\n"<<endl; 255 else 256 cout<<"輸入位置不在當前鏈表節點序號范圍內"<<endl<<endl; 257 break; 258 case 8: //返回值最大的元素及其在表中位置 259 ElemType MaxVal; 260 if(findMaxList_L(L,i,MaxVal)) 261 cout<<"當前鏈表中最大的元素為"<<MaxVal<<",其位置為"<<i<<".\n"<<endl; 262 else 263 cout<<"當前為空鏈表"<<endl<<endl; 264 break; 265 case 9: //就地逆置 266 if(reverseList_L(L)) 267 cout<<"就地成功逆置鏈表"<<endl<<endl; 268 else 269 cout<<"此表為空鏈表"<<endl<<endl; 270 271 break; 272 case 10: //刪除表中所有值為item的數據元素 273 if(L->next==NULL) 274 cout<<"當前為空鏈表"<<endl<<endl; 275 else{ 276 cout<<"請輸入要刪除鏈表的一個元素:"; 277 cin>>x; 278 if(delItemList_L(L,x)) 279 cout<<"刪除成功,已經將元素"<<x<<"從鏈表中刪除.\n"<<endl; 280 else 281 cout<<"此鏈表沒有"<<x<<"這個元素.\n"<<endl; 282 } 283 break; 284 case 11: //刪除單鏈表中值最小的數據元素 285 if(delMinList_L(L,i,x)) 286 cout<<"已經刪除了該表中"<<i<<"位置上的最小元素"<<x<<".\n"<<endl; 287 else 288 cout<<"當前為空表"<<endl; 289 break; 290 } 291 } 292 return 0; 293 }