10、数据结构【基本操作】

数据结构

一、顺序表的基本操作

  1 实验一:顺序表的基本操作。
  2  
  3 编写一个完整的程序,实现顺序表的建立、插入、删除、输出等基本运算。
  41)       建立一个顺序表,含有n个数据元素。
  52)       输出顺序表及顺序表的长度。
  63)       在顺序表中删除值为x的结点或者删除给定位置i的结点。
  74)       将顺序表就地逆置,即利用原表的存储空间将线性表(a1,a2,...,an)逆置为(an,an-1,...,a1)。
  85)       将顺序表按升序排序。
  96)       设顺序表中的数据元素递增有序,将x插入到顺序表的适当位置上,以保持该表的有序性。
 107)       将两个顺序有序表A和B合并为一个有序表C。
 118)       在主函数中设计一个简单的菜单,分别测试上述算法。
 12  
 13 #include<stdio.h>
 14 #include<stdlib.h>
 15  
 16 #define LIST_INIT_SIZE 100
 17 #define LISTINCREMENT 10
 18 #define OK 1
 19 #define OVERFLOW -2
 20 #define ERROR 0
 21  
 22 typedef int ElemType;
 23  
 24 typedef struct{
 25          ElemType *elem;
 26          int length;
 27          int listsize;
 28 }SqList;
 29  
 30 int cmp(const void *a,const void *b)
 31 {
 32          return *(int*)a-*(int*)b;
 33 }
 34  
 35  
 36 //创建一个空表
 37 int InitList(SqList &L)
 38 {
 39          L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));//分配空间
 40          if(!L.elem)
 41                   return OVERFLOW;
 42          L.length=0;
 43          L.listsize=LIST_INIT_SIZE;
 44          return OK;
 45 }
 46  
 47 //在创建的空表中插入数据
 48 int ListInsert(SqList &L,int i,ElemType e)
 49 {
 50          ElemType* newbase;
 51          //ElemType* q;
 52          if(i<0 || i>L.length+1)
 53                    return ERROR;
 54          if(L.length>=L.listsize)//当前空间已满,增加新空间
 55          {
 56                    newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
 57                    if(!newbase)
 58                             return OVERFLOW;
 59                    L.elem=newbase;
 60                    L.listsize+=LISTINCREMENT;
 61          }
 62         
 63          L.elem[i]=e;
 64          //printf("%d ",L.elem[i]);
 65          L.length++;
 66          return OK;
 67 }
 68  
 69 //删除位置为i的节点
 70 int ListDelete(SqList &L,int i)
 71 {
 72          ElemType* p;
 73          ElemType* q;
 74          if(i<0 || i>L.length)
 75                    return ERROR;
 76          p=&(L.elem[i-1]);
 77          //e=*p;
 78          q=L.elem+L.length-1;
 79          for(++p;p<=q;p++)
 80                    *(p-1)=*p;
 81          L.length--;
 82          return OK;
 83 }
 84  
 85 //在顺序表中删除数据x
 86 int DeleteX(SqList &L, int x)
 87 {
 88          ElemType* p;
 89  
 90          int i;
 91          for(i=0;i<L.length;i++)
 92                    if(L.elem[i]==x)
 93                    {
 94                             break;
 95                    }
 96                    p=&L.elem[i];
 97                    //free(p);
 98                    for(int j=i;j<L.length-1;j++)
 99                    {
100                             L.elem[j]=L.elem[j+1];
101                    }
102                    L.length--;
103                    return OK;
104 }
105  
106 //反转顺序表
107 int TurnArrond(SqList &L)//翻转顺序表
108 {
109          ElemType* p;
110          ElemType* q;
111          int t;
112          p=&(L.elem[0]);
113          q=L.elem+L.length-1;
114          for(p;p<q;p++,q--)
115          {
116                    t=*q;
117                    *q=*p;
118                    *p=t;
119          }
120          return OK;
121 }
122  
123 //升序排列顺序表
124 int ABC(SqList &L)
125 {
126          int a[10000];
127          int i;
128          for(i=0;i<L.length;i++)
129                    a[i]=L.elem[i];
130  
131          qsort(a,L.length,sizeof(a[0]),cmp);
132         
133          for(i=0;i<L.length;i++)
134                    L.elem[i]=a[i];
135          return OK;
136 }
137  
138 //把顺序表升序排列后插入元素e
139 int ListInsertABC(SqList &L,ElemType e)
140 {
141          ElemType* newbase;
142          int i,j;
143          if(L.length+1>=L.listsize)//当前空间已满,增加新空间
144          {
145                    newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
146                    if(!newbase)
147                             return OVERFLOW;
148                    L.elem=newbase;
149                    L.listsize+=LISTINCREMENT;
150          }
151         
152          for(i=0;i<L.length;i++)
153                    if(e<L.elem[i])
154                             break;
155                   
156                    for(j=L.length;j>i;j--)
157                    {
158                             L.elem[j]=L.elem[j-1];
159                    }
160                    L.length++;
161                    L.elem[j]=e;
162                    //printf("%d ",L.elem[i]);
163                    return OK;
164 }
165  
166 //合并顺序表L,L1为L2
167 int MergeList(SqList L,SqList L1,SqList &L2)
168 {
169          ElemType* pa;
170          ElemType* pb;
171          ElemType* pc;
172          ElemType* pa_last;
173          ElemType* pb_last;
174          pa=L.elem;
175          pb=L1.elem;
176 //      L2.elem=pc;
177          L2.listsize=L.listsize+L1.listsize;
178          pc=L.elem=(ElemType*)malloc(L2.listsize * sizeof(ElemType));
179         
180          pa_last=L.elem+L.length-1;
181          pb_last=L1.elem+L1.length-1;
182          while(pa<=pa_last && pb<=pb_last)
183          {
184                    if(*pa<=*pb)
185                             *pc++=*pa++;
186                    else
187                             *pc++=*pb++;
188          }
189          while(pa<=pa_last)
190                    *pc++=*pa++;
191          while(pb<=pb_last)
192                    *pc++=*pb++;
193  
194          for(int i=0;i<L2.length;i++)
195                    printf("%d ",L2.elem[i]);
196          return OK;
197 }
198  
199 //打印菜单
200 void printScreen()
201 {
202          //printf("1.建立一个顺序表,含有n个数据元素。\n");
203          printf("1.输出顺序表L1及其长度\n");
204          printf("2.删除给定位置i的结点\n");
205          printf("3.在顺序表中删除值为x的结点\n");
206          printf("4.逆置顺序表\n");
207          printf("5.将顺序表按升序排序\n");
208          printf("6.设顺序表中的数据元素递增有序,将x插入到顺序表的适当位置上,以保持该表的有序性\n");
209          printf("7.将两个顺序有序表L和L1合并为一个有序表L2\n");
210          printf("0.退出操作系统。\n");
211          printf("请输入需要的操作序号:");
212 }
213  
214 //输出顺序表L
215 void printSqList(SqList &L)
216 {
217          int i;
218          for(i=0;i<L.length;i++)
219                    printf("%d ",L.elem[i]);
220          printf("\n");
221 }
222  
223 int main()
224 {
225          SqList L,L1,L2;
226          InitList(L);
227          InitList(L1);
228          InitList(L2);
229          int n,e,muse,i,x;
230          bool flag;
231          //建立第一个的顺序表
232          printf("请输入第一个数据表的长度:");
233          scanf("%d",&n);
234          printf("请以次输入长度为%d的顺序表:",n);
235          for(i=0;i<n;i++)
236          {
237                    scanf("%d",&e);
238                    ListInsert(L,i,e);//依次在第i个位置插入顺序表
239          }
240          printf("第一个顺序表的次序为:");
241          printSqList(L);
242         
243          //建立第二个顺序表
244          printf("建立第二个顺序表,请输入要第二个建立数据表的长度:");
245          scanf("%d",&n);
246          printf("请以次输入长度为%d的顺序表:",n);
247          for(i=0;i<n;i++)
248          {
249                    scanf("%d",&e);
250                    ListInsert(L1,i,e);//依次在第i个位置插入顺序表
251          }
252          printf("第二个顺序表的次序为:");
253          printSqList(L1);
254         
255          //打印菜单
256          printScreen();
257          scanf("%d",&muse);
258          flag=true;
259          while(1)
260          {
261                    switch(muse)
262                    {
263                    case 0:
264                             flag=false;
265                             break;
266                    case 1:
267                             printf("顺序表的长度为:");
268                             printf("%d\n",L.length);
269                             break;
270                    case 2:
271                             printf("请输入要删除的节点:");
272                             scanf("%d",&i);//删除顺序表的节点
273                             if(ListDelete(L,i))
274                             {
275                                      printf("删除成功!\n");
276                                      printSqList(L);
277                             }
278                             else
279                                      printf("删除失败!\n");
280                             break;
281                    case 3:
282                             printf("请输入要删除的节点x的值:");
283                             scanf("%d",&x);
284                             if(DeleteX(L,x))
285                             {
286                                      printf("删除成功!\n顺序表为:");
287                                      printSqList(L);
288                             }
289                             else
290                                      printf("删除失败!\n");
291                             break;
292                    case 4:
293                             //逆序顺序表
294                             if(TurnArrond(L))
295                             {
296                                      printf("逆序成功!\n");
297                                      printf("顺序表的次序为:");
298                                      printSqList(L);
299                             }
300                             else
301                                      printf("逆序失败!\n");
302                             break;
303                    case 5:
304                             //顺序表升序排列
305                             if(ABC(L))
306                             {
307                                      printf("顺序表升序排列成功!\n");
308                                      printf("顺序表的次序为:");
309                                      printSqList(L);
310                             }
311                             else
312                                      printf("顺序表升序排列失败!\n");
313                            
314                             printf("请输入要插入的数据:");
315                             scanf("%d",&e);
316                             if(ListInsertABC(L,e))
317                             {
318                                      printf("顺序插入成功!\n");
319                                      printf("顺序表的次序为:");
320                                      printSqList(L);
321                             }
322  
323                             else
324                                      printf("顺序插入失败!\n");
325                             break;
326                    case 6:
327                             ABC(L);
328                             printf("请输入要插入的数字x的值:");
329                             scanf("%d",&x);
330                             if(ListInsertABC(L,x))
331                             {
332                                      printf("操作成功!\n");
333                                      printf("顺序表的次序为:");
334                                      printSqList(L);
335                             }
336                             else printf("操作失败!\n");
337                             break;
338                    case 7:
339                             if(MergeList(L,L1,L2))
340                             {
341                                      printf("顺序表L,L1合并成功!\n");
342                                      //printf("顺序表的次序为:");
343                                      //printSqList(L2);
344                             }
345                             else
346                                      printf("顺序表合并失败!\n");
347                             break;
348                    default:
349                             break;
350                    }
351                    if(!flag)
352                             break;
353                    printf("\n请输入你要的下一步操作序号:");
354                    scanf("%d",&muse);
355          }
356  
357         
358          if(L.elem)
359                    free(L.elem);
360          if(L1.elem)
361                    free(L1.elem);
362          if(L2.elem)
363                    free(L2.elem);
364         
365         
366          return 0;
367 }
顺序表的基本操作

二、单链表的基本操作

  1 实验二:单链表的基本操作
  2  
  3 编写一个完整的程序,实现单链表的建立、插入、删除、输出等基本操作。
  41)建立一个带头结点的单链表。
  52)计算单链表的长度,然后输出单链表。
  63)查找值为x的直接前驱结点q。
  74)删除值为x的结点。
  85)把单向链表中元素逆置(不允许申请新的结点空间)。
  96)已知单链表中元素递增有序,请写出一个高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度(注意:mink和maxk是给定的两个参变量,他们的值可以和表中的元素相同,也可以不同)。
 107)同(6)的条件,试写一高效的算法,删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同),同时释放被删结点空间,并分析你的算法时间复杂度。
 118)利用(1)建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
 129)在主函数中设计一个简单的菜单,分别测试上述算法。
 13  
 14 # include <stdio.h>
 15 # include <stdlib.h> 
 16  
 17 typedef struct node
 18 {
 19          int data;
 20          struct node * next;
 21 }Lnode, * LinkList;                                //LinkList的数据类型是struct node *;
 22  
 23 int m=sizeof(Lnode);                            //Lnode结构体变量,结点变量;
 24  
 25 //建立新的链表
 26 void Bulid_List(LinkList root)   
 27 {
 28          int num;
 29          LinkList s,p;                            //定义了两个结构体指针变量;
 30          s=root->next;                            //root->next和s同时指向第一个结点;
 31          int n;
 32          printf("请输入新建链表的长度n数据:\n");
 33          scanf("%d",&n);
 34          printf("请依次建立链表:");
 35          for(int i=0;i<n;i++)
 36          {
 37                    scanf("%d",&num);
 38                    s->data=num;
 39                    p=(LinkList)malloc(m);        //动态分配内存空间
 40                    s->next=p;
 41                    s=p;
 42                    s->next=NULL;
 43          }
 44          printf("链表已建立!\n");
 45 }
 46  
 47 //对链表的输出,包括长度和元素
 48 void OutPut_list(LinkList root)    
 49 {
 50          int len=0;
 51          LinkList s;
 52          s=root->next;
 53          if(s->next==NULL)        
 54                    printf("单链表无数据,请先新建单链表。\n");
 55          else
 56          {
 57                    while(s->next!=NULL) 
 58                    {
 59                             s=s->next;
 60                             len++;
 61                    }
 62                    printf("单链表的长度为:%d\n",len);
 63                    printf("单链表的数据如下:\n");
 64                    s=root->next;
 65                    while(s->next!=NULL)
 66                    {
 67                             printf("%d ",s->data);
 68                             s=s->next;
 69                    }
 70                    printf("\n");
 71          }
 72 }
 73  
 74 //查询元素 
 75 void Find_list(LinkList root,int x)  
 76 {
 77          LinkList s,p;
 78          if(root->next->next==NULL)  
 79                    printf("单链表无数据,请先新建单链表。\n");
 80          else
 81          {
 82                    s=root->next;
 83                    p=root->next->next;
 84                    if(s->data==x)              
 85                             printf("此X值无前驱结点。\n");
 86                    else
 87                    {
 88                             while(p->next!=NULL)
 89                             {
 90                                      if(p->data==x)              
 91                                      {
 92                                                printf("此X值的前驱结点的值为:%d\n",s->data);
 93                                                return;                    
 94                                      }
 95                                      else
 96                                      {
 97                                                s=p;
 98                                                p=p->next;
 99                                      }
100                             }
101                             printf("此链表不存在值为X的结点。\n");
102                    }
103          }
104          return;
105 }
106  
107 //删除元素 
108 void Delete_list(LinkList root,int x) 
109 {
110          LinkList s;
111          int flag;                        
112          if(root->next->next==NULL)        
113                    printf("单链表无数据,请先新建单链表。\n");
114          else                               
115          {
116                    flag=0;
117                    while(root->next!=NULL)
118                    {
119                             if(root->next->data==x)  
120                             {
121                                      if(root->next->next!=NULL)
122                                      {
123                                                s=root->next;
124                                                root->next=root->next->next;
125                                                free(s);
126                                                flag=1;
127                                                return;
128                                      }
129                             }
130                             else
131                                      root=root->next;
132                    }
133                    if(flag==0)
134                             printf("待删除的数据不存在。\n");
135          }
136          return;    
137 }
138  
139 LinkList NEW()
140 {
141          LinkList new_node;
142          new_node=(LinkList)malloc(m);
143          new_node->next=NULL;
144          new_node->data=0;
145          return new_node;
146 }
147  
148 //分解链表
149 void Divid(LinkList head)
150 {
151          LinkList head_odd,head_even,p_odd,p_even,p,s;
152          head_odd=NEW();
153          head_even=NEW();
154          p=head->next;
155          p_odd=head_odd;
156          p_even=head_even;
157          while(p!=NULL)
158          {
159                    s=p;
160                    p=p->next;
161                    if(s->data%2==0)
162                    {
163                             p_odd->next=s;
164                             p_odd=p_odd->next;
165                             p_odd->next=NULL;
166                    }
167                    else
168                    {
169                             p_even->next=s;
170                             p_even=p_even->next;
171                             p_even->next=NULL;
172                    }
173          }
174          printf("构建成功!\n");
175          printf("奇数链表为:");
176          p=head_even->next;
177          while(p->next!=NULL)
178          {
179                    printf("%d ",p->data);
180                    p=p->next;
181          }
182          printf("\n偶数链表为:");
183          p=head_odd;
184          while(p->next!=NULL)
185          {
186                    printf("%d ",p->next->data);
187                    p=p->next;
188          }
189          printf("\n");
190 }
191  
192 //6
193 void DelteAndFree_list(LinkList root) 
194 {
195          LinkList s,p,t,k;
196          int min,max;
197          if(root==NULL)        
198                    printf("单链表无数据,请先新建单链表。\n");
199          else
200          {
201  
202                    printf("请输入所要min的值,max的值(min < max):\n");
203                    scanf("%d%d",&min,&max);
204                    s=root->next;
205                    p=root;
206                    while(s->data<min)        
207                    {
208                             s=s->next;
209                             p=p->next;
210                    }
211                    t=p;
212                    while(s->data<max)        
213                    {
214                             s=s->next;
215                             t=t->next;
216                    }
217                    s=p->next;                
218                    p->next=t->next->next;
219                    t->next=NULL;
220                    while(s->next!=NULL)         
221                    {
222                             k=s;
223                             s=s->next;
224                             free(k);
225                    }
226                    free(s);
227          }
228          return;
229         
230 }
231  
232 //删除公共元素 
233 void DeleteCommon_list(LinkList root) 
234 {
235          LinkList s,p,t;
236          if(root->next->next==NULL)    
237                    printf("单链表无数据,请先新建单链表。\n");
238          else
239          {
240                    s=root->next;
241                    p=root->next->next;
242                    while(p->next!=NULL)
243                    {
244                             if(s->data==p->data)  
245                             {
246                                      t=p;
247                                      p=p->next;
248                                      s->next=p;
249                                      free(t);
250                             }
251                             else
252                             {
253                                      s=s->next;
254                                      p=p->next;
255                             }
256                    }
257          }
258          return;
259 }
260  
261  
262 //链表的逆置 
263 void Reserve_list(LinkList root)   
264 {
265          LinkList s,p,t;
266          s=root->next;
267          root->next=NULL;
268          while(s->next!=NULL)
269          {
270                    p=s->next;
271                    s->next=root->next;
272                    root->next=s;
273                    s=p;
274          }
275          LinkList head;
276          head=(LinkList)malloc(m);
277          head->next=NULL;
278          t=root;
279          while(t->next!=NULL)
280          {
281                    t=t->next;
282          }
283          t->next=head;
284          return;
285 }
286  
287 //打印菜单
288 void print()
289 {
290          printf("\n菜单如下:\n");
291          printf("1.建立单链表\n");
292          printf("2.计算单链表的长度并输出\n");
293          printf("3.查找值为x的直接前驱结点q\n");
294          printf("4.删除值为x的节点\n");
295          printf("5.逆置单链表\n");
296          printf("6.将单链表递增排序后删除表中所有值大于mink且小于maxk的元素\n");
297          printf("7.将单链表递增排序后删除表中所有值相同的多余元素\n");
298          printf("8.分解单链表,一个为奇数,另一个为偶数\n");
299          printf("0.EXIT\n\n");
300          printf("请输入你选菜单的数字:\n");
301 }
302  
303 //循环菜单
304 int main(void)
305 {
306          LinkList root;
307          int x;
308          root = (LinkList)malloc(m);
309          root->next = NULL;
310          root->next = (LinkList)malloc(m);
311          root->next->next = NULL;
312          bool flag;
313          int op;
314          print();
315         
316          //show_arr(&arr);
317         
318          while(scanf("%d",&op)!=EOF)
319          {
320                    flag=true;
321                    switch(op)
322                    {
323                    case 0:
324                             flag=false;                          
325                             break;
326                    case 1:
327                             Bulid_List(root);
328                             break;
329                    case 2:
330                             OutPut_list(root);
331                             break;
332                    case 3:
333                             printf("请输入所要查找的x:\n"); 
334                             scanf("%d",&x);
335                             Find_list(root,x);
336                             break;
337                    case 4:
338                             printf("请输入所要删除值x:\n");
339                             scanf("%d",&x);
340                             Delete_list(root,x);
341                             break;
342                    case 5:
343                             Reserve_list(root);
344                             break;
345                    case 6:
346                             DelteAndFree_list(root);
347                             break;
348                    case 7:
349                             DeleteCommon_list(root);
350                             break;
351                    case 8:
352                             Divid(root);
353                             break;
354                    default:
355                             printf("您真笨,输入的数字非法,程序已退出!!\n");
356                             break;
357                    }
358  
359                    if(!flag)
360                    {
361                             printf("程序将退出!!谢谢使用!!\n");
362                             break;
363                    }
364                    else{
365                             print();
366                    }
367          }
368         
369          return 0;
370 }
单链表的基本操作

三、栈和队列的基本操作

  1 实验四:栈和队列的基本操作
  2  
  31)采用链式存储实现栈的初始化、入栈、出栈操作。
  42)采用顺序存储实现栈的初始化、入栈、出栈操作。
  53)采用链式存储实现队列的初始化、入队、出队操作。
  64)采用顺序存储实现循环队列的初始化、入队、出队操作。
  75)在主函数中设计一个简单的菜单,分别测试上述算法。
  8  
  9 综合训练:(1)利用栈实现表达式求值算法。
 102)利用栈实现迷宫求解。
 113)编写c语言程序利用队列打印一个杨辉三角形的前n行。
 12 1
 13 1  1
 14 1  2  1
 15 1  3  3  1
 16 1  4  6  4  1
 17  
 18 #include<stdio.h>
 19 #include"xxb.h"
 20  
 21 int main()
 22 {
 23         
 24          print();
 25          int ncase, n1, n2, n3, n4;
 26          bool flag = true;
 27          bool f1, f2, f3, f4;
 28          SqStack s;
 29          LinkLStack ls;
 30          SqQueue Q;
 31          LinkQueue LQ;
 32          int e;
 33          while(scanf("%d",&ncase) != EOF)
 34          {
 35                    f1 = true;
 36                    f2 = true;
 37                    f3 = true;
 38                    f4 = true;
 39                    switch(ncase)
 40                    {
 41                    case 1:
 42                             print1();
 43                             IniLStack(ls);
 44                             while(scanf("%d",&n1) != EOF)
 45                             {
 46                                     
 47                                      switch(n1)
 48                                      {
 49                                      case 1:
 50                                                if(IniLStack(ls))
 51                                                         printf("链式栈建立成功!\n");
 52                                                else
 53                                                         printf("链式栈建立失败!\n");
 54                                                break;
 55                                      case 2:
 56                                                if(PushLStack(ls, e))
 57                                                         printf("入栈成功!\n");
 58                                                else
 59                                                         printf("入栈失败!\n");
 60                                                break;
 61                                      case 3:
 62                                                if(PopLStack(ls, e))
 63                                                         printf("e = %d出栈成功!\n", e);
 64                                                else
 65                                                         printf("栈为空!\n");
 66                                                break;
 67                                               
 68                                      case 0:
 69                                                f1 = false;
 70                                                break;
 71                                      default:
 72                                                printf("     输入有误,请重新输入!\n");
 73                                                break;
 74                                      }
 75                                      if(!f1)
 76                                                break;
 77                                      print1();
 78                             }
 79                             break;
 80                    case 2:
 81                             print2();
 82                             while(scanf("%d",&n2) != EOF)
 83                             {
 84                                      switch(n2)
 85                                      {
 86                                      case 1:
 87                                                if(Initack(s))
 88                                                         printf("顺序栈建立成功!\n");
 89                                                else
 90                                                         printf("顺序建立失败!\n");
 91                                                break;
 92                                      case 2:
 93                                                if(Push(s,e))
 94                                                         printf("入栈成功!\n");
 95                                                else
 96                                                         printf("入栈失败!\n");
 97                                                break;
 98                                      case 3:
 99                                                if(!Pop(s, e))
100                                                         printf("顺序栈为空!\n");
101                                                else
102                                                         printf("e = %d出栈成功!\n", e);
103                                                break;
104                                      case 0:
105                                                f2 = false;
106                                                break;
107                                      default:
108                                                printf("     输入有误,请重新输入!\n");
109                                                break;
110                                      }
111                                      if(!f2)
112                                                break;
113                                      print2();
114                             }
115                             break;
116                    case 3:
117                             print3();
118                             while(scanf("%d",&n3) != EOF)
119                             {
120                                      switch(n3)
121                                      {
122                                      case 1:
123                                                if(InitQueue(LQ))
124                                                         printf("链式队列构造成功!\n");
125                                                else
126                                                         printf("链式队列构造失败!\n");                                        
127                                                break;
128                                      case 2:
129                                                printf("请输入如队列元素e=");
130                                                scanf("%d",&e);
131                                                if(EnQueue(LQ, e))
132                                                         printf("链式队列入列成功!\n");
133                                                else
134                                                         printf("链式队列入列失败!\n");
135                                                break;
136                                      case 3:
137                                                if(DeQueue(LQ, e))
138                                                         printf("e = %d出队列成功!\n", e);
139                                                else
140                                                         printf("队列为空!\n");
141                                                break;
142                                      case 0:
143                                                f4 = false;
144                                                break;
145                                      default:
146                                                printf("     输入有误,请重新输入!\n");
147                                                break;
148                                      }
149                                      if(!f4)
150                                                break;
151                                      print4();
152                             }
153                             break;
154                    case 4:
155                             print4();
156                             while(scanf("%d",&n4) != EOF)
157                             {
158                                      switch(n4)
159                                      {
160                                                case 1:
161                                                if(InitQueue(Q))
162                                                         printf("顺序队列初始化成功!\n");
163                                                else
164                                                         printf("顺序队列初始化失败!\n");                                             
165                                                break;
166                                      case 2:
167                                                printf("请输入如队列元素e=");
168                                                scanf("%d",&e);
169                                                if(EnQueue(Q, e))
170                                                         printf("插入队列成功!\n");
171                                                else
172                                                         printf("插入失败!\n");
173                                                break;
174                                      case 3:
175                                                if(DeQueue(Q, e))
176                                                         printf("e = %d出队列成功!\n", e);
177                                                else
178                                                         printf("队列为空!\n");
179                                                break;
180                                      case 0:
181                                                f3 = false;
182                                                break;
183                                      default:
184                                                printf("     输入有误,请重新输入!\n");
185                                                break;
186                                      }
187                                      if(!f3)
188                                                break;
189                                      print3();
190                             }
191                             break;
192                    case 0:
193                             flag = false;
194                            
195                             break;
196                    default:
197                             printf("     输入错误,请重新输入,谢谢!\n");
198                             break;
199                    }
200                    if(!flag)
201                             break;
202                    print();
203          }
204         
205          return 0;
206 }
栈和队列的基本操作

四、二叉树的基本操作

  1 实验五:二叉树的基本操作
  2  
  31)输入字符序列,建立二叉链表。
  42)先序、中序、后序遍历二叉树:递归算法。
  53)中序遍历二叉树:非递归算法。(最好也能实现先序、后序非递归算法)
  64)求二叉树的高度 。
  75)求二叉树的叶子个数。
  86)借助队列实现二叉树的层次遍历。
  97)在主函数中设计一个简单的菜单,分别调试上述算法。
 10  
 11 #include<stdio.h>
 12 #include<stdlib.h>
 13  
 14 #define OK 1
 15 #define ERROR 0
 16 #define OVERFLOW -1
 17 #define LIST_INT_SIZE 100
 18 #define LISTINCREMENT 10
 19  
 20 int dep, count= 0;
 21  
 22 typedef int Status;
 23 typedef char TElemType;
 24  
 25 typedef struct BiTNode{
 26          TElemType data;
 27          struct BiTNode *lchild, *rchild;
 28 }BiTNode, *BiTree;
 29  
 30 //建立二叉树
 31 Status CreateBiTree(BiTree &T)
 32 {
 33          char ch;
 34         
 35          getchar();
 36          scanf("%c", &ch);
 37          if(ch == ' '|| ch == '\n')
 38          {
 39                    T = NULL;
 40                    return ERROR;
 41          }
 42          else
 43          {
 44                    T = (BiTree)malloc(sizeof(BiTNode));
 45                    T->data = ch;
 46                    printf("请输入%c的左孩子:", T->data);
 47                    CreateBiTree(T->lchild);
 48                    printf("请输入%c的右孩子:", T->data);
 49                    CreateBiTree(T->rchild);
 50                    return OK;
 51          }
 52 }
 53  
 54  
 55  
 56 //主菜单
 57 void print()
 58 {
 59          printf("\n菜单如下:\n");
 60          printf("1 . 输入字符序列,建立二叉链表\n");
 61          printf("2 . 先序、中序、后序遍历二叉树:递归算法\n");
 62          printf("3 . 先序、中序、后序遍历二叉树:非递归算法\n");
 63          printf("4 . 求二叉树的高度 \n");
 64          printf("5 . 求二叉树的叶子个数\n");
 65          printf("6 . 借助队列实现二叉树的层次遍历\n");
 66          printf("0 . EXIT\n请选择操作序号:");
 67 }
 68  
 69 //先序、中序、后序遍历二叉树:递归算法
 70 void print2()
 71 {
 72          printf("\n递归算法遍历二叉树,菜单如下:\n");
 73          printf("1.先根遍历\n");
 74          printf("2.中序遍历\n");
 75          printf("3.后续遍历\n");
 76          printf("0.退出\n");
 77          printf("请输入二级菜单选择:");
 78 }
 79  
 80 Status Visit(BiTree T)
 81 {
 82          if(T)
 83          {
 84                    printf("%c ", T->data);
 85                    return OK;
 86          }
 87 }
 88  
 89 Status PrintElement(TElemType e)
 90 {
 91          printf(" %c ", e);
 92          return OK;
 93 }
 94  
 95 //先序
 96 Status PreOrderTraverse(BiTree T, Status (*Visit)(TElemType e))
 97 {
 98          if(T)
 99          {
100                    if(Visit(T->data))
101                             if(PreOrderTraverse(T->lchild, Visit))
102                                      if(PreOrderTraverse(T->rchild, Visit))
103                                                return OK;
104                             return ERROR;
105          }
106          else
107                    return OK;
108 }
109  
110 //中序
111 Status MidOrderTraverse(BiTree T, Status (*Visit)(TElemType e))
112 {
113          if(T)
114          {
115                    if(MidOrderTraverse(T->lchild, Visit))
116                             if(Visit(T->data))
117                                      if(MidOrderTraverse(T->rchild, Visit))
118                                                return OK;
119                             return ERROR;
120          }
121          else
122                    return OK;
123 }
124 //后序
125 Status LastOrderTraverse(BiTree T, Status (*Visit)(TElemType e))
126 {
127          if(T)
128          {       
129                    if(LastOrderTraverse(T->lchild, Visit))
130                             if(LastOrderTraverse(T->rchild, Visit))
131                                      if(Visit(T->data))
132                                                return OK;
133                             return ERROR;
134          }
135          else
136                    return OK;
137 }
138  
139 //求树的叶子的个数,和打印出叶子
140 Status LeafNumTree(BiTree T)
141 {
142          int lnum,rnum;
143          if(T!=NULL)
144          {
145                    if(T->lchild==NULL && T->rchild==NULL)
146                             return 1;
147                    else
148                    {
149                             lnum=LeafNumTree(T->lchild);
150                             rnum=LeafNumTree(T->rchild);
151                             return lnum+rnum;
152                    }
153          }
154          return 0;
155 }
156  
157 //求二叉树的高度
158 Status BiTreeDepth(BiTree T)
159 {
160          int l,r;
161          if(T)
162          {
163                    l=BiTreeDepth(T->lchild);
164                    r=BiTreeDepth(T->rchild);
165                    if(l>=r)
166                             dep += l;
167                    else dep += r;
168          }
169          else
170                    return 1;
171 }
172  
173 //先序、中序、后序遍历二叉树:非递归算法
174 void print3()
175 {
176          printf("\n非递归算法遍历二叉树,菜单如下:\n");
177          printf("1.先根遍历\n");
178          printf("0.退出\n");
179          printf("请输入二级菜单选择:");
180 }
181  
182 typedef struct QueueNode
183 {
184          BiTree e;
185          struct QueueNode *next;
186 }QueueNode,*QueuePtr;                   //定义队列结点结构
187 typedef struct
188 {
189          QueuePtr front;
190          QueuePtr rear;
191 }LinkQueue;  
192  
193  
194 //栈的顺序存储表示
195  typedef struct
196  { BiTNode *base;   //栈底指针
197    BiTNode *top;    //栈顶指针
198    int   stacksize; //当前已分配的存储空间
199  }SqStack;
200  
201 //初始化一个带头结点的队列
202 void InitQueue(LinkQueue &q)
203 {
204          q.front=q.rear=(QueuePtr)malloc(sizeof(QueueNode));
205          q.front->next=NULL;
206 }
207  
208 //入队列
209 void enqueue(LinkQueue &q,BiTree p)
210 {
211          QueuePtr s;
212          int first=1;
213          s=(QueuePtr)malloc(sizeof(QueueNode));
214          s->e =p;
215          s->next=NULL;
216          q.rear->next=s;
217          q.rear=s;
218 }
219  
220 //出队列
221 void dequeue(LinkQueue &q,BiTree &p)
222 {
223          char data;
224          QueuePtr s;
225          s=q.front->next;
226          p=s->e ;
227     data=p->data;
228          q.front->next=s->next;
229          if(q.rear==s)
230                    q.rear=q.front;
231          free(s);
232          printf("%c\t",data);
233 }
234  
235 //判断队列是否为空
236 Status queueempty(LinkQueue q)
237 {
238          if(q.front->next==NULL)
239                    return 1;
240          return 0;
241 }
242 //按层次遍历树中结点
243 void Traverse(BiTree T)
244 {
245          LinkQueue q;
246          BiTree p;
247          InitQueue(q);
248          p=T;
249          enqueue(q,p);
250          while(queueempty(q)!=1)
251          {
252                    dequeue(q,p);
253                    if(p->lchild!=NULL)
254                             enqueue(q,p->lchild);
255                    if(p->rchild!=NULL)
256                             enqueue(q,p->rchild);
257          }
258          printf("\n");
259 }
260  
261  //建立一个空栈
262  void InitStack(SqStack &S)
263  {    S.base=(BiTree)malloc(LIST_INT_SIZE * sizeof(BiTNode));
264     if(!S.base)
265                    exit(OVERFLOW );//存储分配失败
266     S.top=S.base;
267     S.stacksize=LIST_INT_SIZE;
268  }
269  
270  //压入栈
271  void Push(SqStack & S,BiTree p)
272  { if(S.top-S.base>=S.stacksize)//满栈,追加存储结构
273  {    S.base= (BiTree)realloc(S.base,(S.stacksize+LISTINCREMENT) * sizeof(BiTNode));
274       if(!S.base)  exit(OVERFLOW );//存储分配失败
275            S.top=S.base+S.stacksize;   
276            S.stacksize+=LISTINCREMENT;
277  }
278            *(++S.top)=*p;
279  }
280  
281  //退出栈
282 bool Pop(SqStack &S,BiTree &p)
283 {  if( S.top==S.base)
284  {   printf("空栈\n");
285      return false;
286  }
287      p=(BiTree)malloc( sizeof(BiTNode));
288     *p=*S.top;
289     --S.top;
290     return true;
291  }
292  
293  //判断是否是空栈       
294  bool StackEmpty(SqStack &S)
295  {   if( S.top==S.base) 
296        return true;
297     else
298           return  false ;
299  }
300  
301  
302 Status InOrderTraverAndCountLeaf(BiTree &T,Status(* Vist)(TElemType e))
303 {   int j=0,count=0;
304          BiTree p;
305          p=(BiTNode *)malloc( sizeof(BiTNode));//关键一步
306          p=T;
307     SqStack s;
308          InitStack(s);
309          while(p||!StackEmpty(s))
310          { if(p)
311          {  Push(s,p);//如果p为非空,将p压入栈
312             if(!(p->lchild)&&!(p->rchild))
313                      ++count;//记录叶子节点数
314             p=p->lchild;        
315          }//if
316           else
317           {
318             Pop(s,p);//如果p为空,则p退栈
319             Vist(p->data);
320        p=p->rchild;
321             }//else
322          }//while
323     return  count;
324 }
325  
326 int main()
327 {
328          int n, ncase;
329          int count;
330          bool f, f1, f2, f3;
331          BiTree T;
332          TElemType e;
333          print();
334          while(scanf("%d", &n)!=EOF)
335          {
336                   
337                    f = true;
338  
339                    switch(n)
340                    {
341                    case 1:
342                             printf("输入空格或回车表示此结点为空结束\n请输入头结点:");
343                             if(CreateBiTree(T))
344                                      printf("二叉树建立成功!\n");
345                             else
346                                      printf("二叉树建立失败!\n");
347                             break;
348                    case 2:
349                             print2();
350                             while(scanf("%d", &ncase)!= EOF)
351                             {
352                                      f1 = true;
353                                      switch(ncase)
354                                      {
355                                      case 1:
356                                                printf("先序遍历顺序为:");
357                                                if(PreOrderTraverse(T, PrintElement))
358                                                         printf("先序遍历成功!\n");
359                                                else
360                                                         printf("先序遍历失败!\n");
361                                                break;
362                                      case 2:
363                                                printf("中序遍历顺序为:");
364                                                if(MidOrderTraverse(T, PrintElement))
365                                                         printf("中序遍历成功!\n");
366                                                else
367                                                         printf("中序遍历失败!\n");
368                                                break;
369                                      case 3:
370                                                printf("后序遍历顺序为:");
371                                                if(LastOrderTraverse(T, PrintElement))
372                                                         printf("后序遍历成功!\n");
373                                                else
374                                                         printf("后序遍历失败!\n");
375                                                break;
376                                      case 0:
377                                                f1 = false;
378                                                break;
379                                      default :
380                                                printf("输入错误,请重新输入!\n");
381                                      }
382                                      if(!f1)
383                                                break;
384                                      print2();
385                             }
386                   
387                             break;
388                    case 3:
389                             print3();
390                             while(scanf("%d", &ncase)!= EOF)
391                             {
392                                      f2 = true;
393                                      switch(ncase)
394                                      {
395                                      case 1:
396                                                InOrderTraverAndCountLeaf(T,PrintElement);
397                                                break;
398                                      case 0:
399                                                f2 = false;
400                                                break;
401                                      default :
402                                                printf("输入错误,请重新输入!\n");
403                                      }
404                                      if(!f2)
405                                                break;
406                                      print3();
407                             }
408  
409                             break;
410                    case 4:
411                             dep = 0;
412                             BiTreeDepth(T);
413                             printf("二叉树的高度为:%d\n", dep-1);
414                             break;
415                    case 5:
416                             count = LeafNumTree(T);
417                             printf("二叉树的叶子个数为:%d\n", count);
418                             break;
419                    case 6:
420                             printf("按层次遍历的顺序为:\n");
421                             Traverse(T);
422                             printf("\n");
423                             break;
424                    case 0:
425                             f = false;
426                             break;
427                    default:
428                             printf("输入错误,请重新输入!\n");
429                             break;
430                    }
431                    if(!f)
432                    {
433                             printf("退出程序...\n");
434                             break;
435                    }
436                    print();
437          }
438  
439          return 0;
440 }
二叉树的基本操作

五、哈夫曼编码

  1 实验六:哈夫曼编码
  2  
  3 已知某系统在通信联络中只可能出现8种字符,其概率分别为0.050.290.070.080.140.230.030.11,试设计哈夫曼编码。
  4  
  5 综合训练:试编写一个将百分制分数转换为五级分制的程序。要求其时间性能尽可能好(即平均比较次数尽可能少)。假设学生成绩的分布情况如下:
  6 分数   0-59    60-69    70-79    80-89    90-100
  7 比例   0.05     0.15     0.40     0.30      0.10
  8  
  9 #include<stdio.h>
 10 #include<stdlib.h>
 11 #include<string.h>
 12 #define ERROR 0
 13 #define OK 1
 14 typedef int Status;
 15 typedef struct {//声明赫夫曼树的结点
 16          int weight;
 17          int parent;
 18          int lchild;
 19          int rchild;
 20 }Htnode,*Huffmantree;
 21 typedef char ** Huffmancode;//相当于声明一个二维数组,来记录每个权值对应的编码。
 22 void Select (Huffmantree &HT,int t,int &p,int &q);//选择结点中权值最小的两个结点,用p,q来返回。
 23 void creathuffmantree(Huffmantree &HT,Huffmancode &HC,int *w,int n)//创建赫夫曼树。
 24 {
 25          int m,i,p,q,j,start,s;
 26          if(n<=1)
 27           return;
 28          m=2*n-1;//当n大于1时,就需要2*n-1个结点
 29          HT=(Huffmantree)malloc(sizeof(Htnode)*(m+1));//因为0不存东西,而从1开始存,所以申请m+1个空间。
 30          for(i=1;i<=n;i++)//对叶子结点进行初始化,除权之外全赋值为0。
 31          {
 32                    HT[i].weight=w[i-1];
 33                    HT[i].parent=0;
 34                    HT[i].rchild=0;
 35                    HT[i].lchild=0;
 36          }
 37          for(i=n+1;i<=m;i++)//对非叶子结点进行初始化,所有的值全为0
 38          {
 39                    HT[i].weight=0;
 40                    HT[i].parent=0;
 41                    HT[i].rchild=0;
 42                    HT[i].lchild=0;
 43          }
 44          for(i=n+1;i<=m;i++)//这是创建树的主要步骤,找出权值和最小的两棵树,再把它们合并成一棵树,依次进行,知道走后还剩仅有的一棵树。
 45          {
 46                    Select(HT,i-1,p,q);//这是选择权值最小的两棵树的函数,并用p,q来返回,在上面已经声明过。
 47                    HT[i].weight=HT[p].weight+HT[q].weight;//对刚合并的新树的根结点的权值进行赋值。
 48                    HT[i].lchild=p;//新树的左孩子赋为p;
 49                    HT[i].rchild=q;//新树的右孩子赋为q;
 50              HT[p].parent=i;//把他们的双亲都赋为i;
 51                    HT[q].parent=i;
 52          }
 53          HC=(Huffmancode)malloc(sizeof(char*)*(n+1));//申请一个大小为n+1的存放指针的数组。
 54          char* cd=(char*)malloc(sizeof(char)*n);//申请一个一维数组,作为一个中转站,最后把他复制到HC中的一个数组中。
 55  
 56          for(i=1;i<=n;i++)//对赫夫曼树的数组从1到n进行依次遍历,这是从叶子结点到根节点。
 57          {
 58                    start=n-1;//对这个一位数组进行倒着存,最后正着读取。
 59               cd[start]='\0';
 60                    s=i;
 61                    while(HT[s].parent!=0)
 62                    {
 63                             j=s;
 64                             s=HT[s].parent;
 65                             if(HT[s].lchild==j)//如果该结点是双亲结点的左孩子,应该把它赋为0;
 66                                      cd[--start]='0';
 67                             if(HT[s].rchild==j)//如果该结点是双亲结点的右孩子,应该把它赋为1;
 68                                      cd[--start]='1';
 69                    }
 70                    HC[i]=(char *)malloc(sizeof(char)*(n-start));
 71                    strcpy(HC[i],&cd[start]);//把cd数组里的内容复制到HC[i]里,再用cd去盛其他的编码。
 72          }
 73          free(cd);//最后可以把cd数组给释放了。
 74 }
 75 void Select (Huffmantree & HT,int t,int &min1,int &min2)//选择结点中权值最小的两个结点,用p,q来返回。
 76 {
 77          int i=1,flag=0;
 78          while(flag<2)//这个while循环是为了找出前两棵树的根结点,把他们当成最小的两棵树,以后来做比较,求出最小的两个。
 79          {
 80            if(HT[i].parent!=0)//如果不是根结点,继续朝后找,直到找到根结点。
 81                      i++;
 82            else//如果是根结点,就把他们分别赋给min1和min2.
 83            {
 84                      if(flag==0)
 85              min1=i;
 86                      else
 87                               min2=i;
 88                     flag++;
 89                     i++;
 90            }
 91          }
 92          if(HT[min1].weight>HT[min2].weight)//对min1和min2进行比较,把最小的的付给min1,第二小的付给min2.
 93          {
 94                    t=min1;
 95                    min1=min2;
 96                    min2=t;
 97          }
 98     while(i<=t)//把以后的各个结点的权值与最小的两个比较,调整下,最后得出的就是最小的两个结点。
 99          {
100                    if(HT[i].parent!=0)//如果不是根结点,继续朝后找,直到找到根结点。
101                             i++;
102                    else
103                    {
104                             if(HT[i].weight<=HT[min1].weight)//如果该结点的权值比最小的结点还小,把最小的两个全重新赋值。
105                             {
106                                      min2=min1;
107                                      min1=i;
108                             }
109                             else if(HT[i].weight>=HT[min1].weight&&HT[i].weight<=HT[min2].weight)//如果该结点的权值在最小和第二小之间的话,
110                                      //就把第二小的重新赋值。
111                                      min2=i;
112                             i++;
113                    }
114          }
115  
116 }
117 Status exhuffmantree(Huffmantree &HT,int  m,char *code,int *ex,int &j)//这是解码的函数,m为那棵树的根结点,code是输入的赫夫曼码,
118 //解码后最后给他存到ex数组中,j为数组的长度。
119 {
120          int i=0,k=m;
121          while(code[i]!='\0')//从根结点到叶子节点去匹配,输出最后的那个权值
122          {
123        if(code[i]=='0'&&HT[k].lchild!=0)//如果code[i]是0,并且左孩子不为0,则继续朝叶子结点找。
124             {
125                 k=HT[k].lchild;
126                       i++;
127             }
128             else if(code[i]=='1'&&HT[k].rchild!=0)//如果code[i]是1,并且右孩子不为0,则继续朝叶子结点找。
129             {
130                       k=HT[k].rchild;
131                       i++;
132             }
133             else if(HT[k].rchild==0&&HT[k].lchild==0)//如果是叶子结点,则把它的权值赋给ex[j].
134             {
135                       ex[j]=HT[k].weight;
136                 j++;
137                       k=m;
138             }
139             else//其他的则返回ERROR。
140                       return ERROR;
141          }
142          if(HT[k].rchild==0&&HT[k].lchild==0)//当跳出循环的时候,说明应该到了叶子结点,如果是叶子结点,则把它的权值赋给ex[j].
143          {
144                    ex[j]=HT[k].weight;
145              return OK;
146          }
147          else//其他的则返回ERROR。
148                    return ERROR;
149 }
150 int main()
151 {
152          Huffmantree HT;
153          Huffmancode HC;
154          char Code[100];
155          int i, n,a[100],b[100],j=0,t;
156          printf("输入叶子结点的个数n为:\n");
157          scanf("%d",&n);
158          printf("依次输入n个叶子结点的权值为:\n");
159          for(i=0;i<n;i++)
160                    scanf("%d",&a[i]);
161     creathuffmantree(HT,HC,a,n);
162          printf("输出该赫夫曼树各个叶子结点的编码为:\n");
163          for(i=1;i<=n;i++)
164          {
165                    t=0;
166       while(HC[i][t]!='\0')
167            {
168                      printf("%c",HC[i][t]);
169                      t++;
170            }
171            putchar(' ');
172          }
173          putchar('\n');
174          getchar();
175          printf("输入该赫夫曼树关联的要译码的code数组:\n");
176          gets(Code);
177    exhuffmantree(HT,2*n-1,Code,b,j);
178          printf("输出解码后的各权值为:\n");
179    for(i=0;i<=j;i++)
180             printf("%d ",b[i]);
181    putchar('\n');
182     return 0;          
183 }
哈夫曼编码

六、图的基本操作

  1 实验七:图的基本操作
  2  
  31)键盘输入数据,建立一个有向图的邻接表。
  42)输出该邻接表。
  53)在有向图的邻接表的基础上计算各顶点的度,并输出。
  64)以有向图的邻接表为基础实现输出它的拓扑排序序列。
  75)采用邻接表存储实现无向图的深度优先遍历。
  86)采用邻接表存储实现无向图的广度优先遍历。
  97)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
 108)采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
 119)在主函数中设计一个简单的菜单,分别调试上述算法。
 12  
 13 综合训练:为计算机专业设计教学计划:4个学年,每学年2个学期,开设50门课程,每学期所开课程门数尽量均衡,课程的安排必须满足先修关系。
 14 #include<stdio.h>
 15 #include<stdlib.h>
 16 #include<stack>
 17 #include<queue>
 18 using namespace std;
 19 #define max_vertex_num 20
 20 #define INFINITY  1000000000
 21 typedef struct ArcNode{
 22          int adjvex;
 23          struct ArcNode *nextarc;
 24 }ArcNode;
 25 typedef char vertexType;
 26 typedef struct VNode{
 27          vertexType data;
 28          ArcNode *firstarc;
 29          int count;
 30 }VNode,AdjList[max_vertex_num];
 31 typedef struct{
 32          AdjList vertices;
 33          int vexnum,arcnum;
 34          int degree;
 35  
 36 }ALGraph;//邻接表
 37 typedef struct ArcCell{
 38          int adj;
 39 }ArcCell,AdjMatrix[max_vertex_num][max_vertex_num];
 40 typedef struct{
 41          char vex[max_vertex_num];
 42     AdjMatrix arc;
 43          int vexnum,arcnum;
 44 }MGraph;//邻接矩阵
 45 ALGraph ALG,InsertALG,UALG;
 46 MGraph G;
 47 int visit[max_vertex_num];
 48 struct edge{
 49          char adjvex;
 50          int lowcost;
 51 }closedge[max_vertex_num];
 52 int P[max_vertex_num];
 53 int D[max_vertex_num];
 54 int finial[max_vertex_num];
 55 void print()
 56 {
 57     printf("(1)键盘输入数据,建立一个有向图的邻接表\n");
 58     printf("(2)输出该邻接表\n");
 59     printf("(3)在有向图的邻接表的基础上计算各顶点的度,并输出\n");
 60     printf("(4)以有向图的邻接表为基础实现输出它的拓扑排序序列\n");
 61     printf("(5)采用邻接表存储实现无向图的深度优先遍历\n");
 62     printf("(6)采用邻接表存储实现无向图的广度优先遍历\n");
 63     printf("(7)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法\n");
 64     printf("(8)采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径\n");
 65          printf("(0)退出程序\n");
 66 }
 67 int locatevex(MGraph G,char v)
 68 {//查找顶点在图中的位置
 69          int i=0;
 70          while(i<G.vexnum)
 71          {
 72                    if(v==G.vex[i])
 73                             break;
 74                    else
 75                             i++;
 76          }
 77          return i;
 78 }
 79 void CreateALGraph(ALGraph  &ALG,ALGraph  &InsertALG)
 80 {//创建有向邻接表及其逆邻接表并且其顶点用大写字母表示
 81          int i,j,k;
 82          ArcNode *s,*r;
 83          printf("请输入有向邻接表的顶点数和边数:\n");
 84          scanf("%d%d",&ALG.vexnum,&ALG.arcnum);
 85          for(i=0;i<ALG.vexnum;i++)
 86          {
 87                    ALG.vertices[i].data='A'+i;
 88         ALG.vertices[i].firstarc=NULL;
 89                    InsertALG.vertices[i].data='A'+i;
 90         InsertALG.vertices[i].firstarc=NULL;
 91          }
 92          for(k=0;k<ALG.arcnum;k++)
 93          {
 94                    scanf("%d%d",&i,&j);
 95                    s=(ArcNode*)malloc(sizeof(ArcNode));
 96                    r=(ArcNode*)malloc(sizeof(ArcNode));
 97                    s->adjvex=j;
 98                    s->nextarc=ALG.vertices[i].firstarc;
 99                    ALG.vertices[i].firstarc=s;
100                    r->adjvex=i;
101                    r->nextarc=InsertALG.vertices[j].firstarc;
102                    InsertALG.vertices[j].firstarc=r;
103          }
104  
105  
106 }
107 void CeratUALGraph(ALGraph &UALG)
108 {//用头插法建立无向邻接表
109          int i,j,k;
110          ArcNode *p;
111          printf("请输入无向邻接表的的顶点数和边数:\n");
112          scanf("%d%d",&UALG.vexnum,&UALG.arcnum);
113          for(i=0;i<UALG.vexnum;i++)
114          {
115                    UALG.vertices[i].data='A'+i;
116                    UALG.vertices[i].firstarc=NULL;
117          }
118          for(k=0;k<UALG.arcnum;k++)
119          {
120                    scanf("%d%d",&i,&j);
121                    p=(ArcNode *)malloc(sizeof(ArcNode));
122                    p->adjvex=j;
123                    p->nextarc=UALG.vertices[i].firstarc;
124         UALG.vertices[i].firstarc=p;
125                    p=(ArcNode *)malloc(sizeof(ArcNode));
126                    p->adjvex=i;
127                    p->nextarc=UALG.vertices[j].firstarc;
128         UALG.vertices[j].firstarc=p;
129          }
130  
131 }
132 void CreateUDN(MGraph &G,int a)
133 {//若a==1的时候创建无向邻接矩阵,否则创建有向邻接矩阵
134          int i,j,k,w;
135          char v1,v2;
136          printf("请输入邻接矩阵的顶点数和边数:\n");
137          scanf("%d%d",&G.vexnum,&G.arcnum);
138          getchar();
139          for(i=0;i<G.vexnum;i++)
140                    scanf("%c",&G.vex[i]);
141          for(i=0;i<G.vexnum;i++)
142                    for(j=0;j<G.vexnum;j++)
143                             G.arc[i][j].adj=INFINITY;
144                    for(k=0;k<G.arcnum;k++)
145                    {
146                             getchar();
147                             scanf("%c %c %d",&v1,&v2,&w);
148                             i=locatevex(G,v1);
149                             j=locatevex(G,v2);
150                             G.arc[i][j].adj=w;
151                             if(a==1)
152                             G.arc[j][i].adj=G.arc[i][j].adj;
153                    }
154 }
155 void shuchu(ALGraph ALG)
156 {//遍历邻接表并输出
157          int i;
158          ArcNode *p;
159          for(i=0;i<ALG.vexnum;i++)
160          {
161                    printf("%d %c ",i,ALG.vertices[i].data);
162                    for(p=ALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)
163                             printf("%d ",p->adjvex);
164                    printf("\n");
165          }
166 }
167 void Degree(ALGraph ALG,ALGraph InsertALG)
168 {//计算邻接表的度=邻接表的出度+逆邻接表的的出度
169          int i;
170          ArcNode *p;
171          for(i=0;i<ALG.vexnum;i++)
172          {
173              ALG.vertices[i].count=0;
174                    for(p=ALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)
175                             ALG.vertices[i].count++;
176          }
177          for(i=0;i<ALG.vexnum;i++)
178          {
179              InsertALG.vertices[i].count=0;
180                    for(p=InsertALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)
181                             InsertALG.vertices[i].count++;
182          }
183          for(i=0;i<ALG.vexnum;i++)
184          {
185                    printf("%c的度为:%d\n",'A'+i,ALG.vertices[i].count+InsertALG.vertices[i].count);
186          }
187  
188 }
189 void dfs(ALGraph UALG,int v)
190 {//深度优先遍历
191          ArcNode *p;
192          visit[v]=1;
193          printf("%c\n",UALG.vertices[v].data);
194          p=UALG.vertices[v].firstarc;
195          while(p)
196          {
197                    if(!visit[p->adjvex])
198                             dfs(UALG,p->adjvex);
199                    p=p->nextarc;
200          }
201  
202 }
203 void DFSTraverse(ALGraph UALG)
204 {
205  
206          for(int i=0;i<UALG.vexnum;i++)
207                    visit[i]=0;
208          for(i=0;i<UALG.vexnum;i++)
209               if(!visit[i])
210                              dfs(UALG,i);
211                     printf("\n");
212 }
213 void BFSTraverse(ALGraph UALG)
214 {//广度优先遍历
215          ArcNode *p;
216          int v;
217          queue<int>q;
218          for(int i=0;i<UALG.vexnum;i++)
219                    visit[i]=0;
220          for(i=0;i<UALG.vexnum;i++)
221                    if(!visit[i]){
222                             visit[i]=1;
223                             printf("%c\n",UALG.vertices[i].data);
224                             q.push(i);
225                             while(!q.empty())
226                             {
227                                      v=q.front();
228                                      q.pop();
229                                      p=UALG.vertices[v].firstarc;
230                                      while(p)
231                                      {
232                                                if(!visit[p->adjvex])
233                                                {
234                                                         visit[p->adjvex]=1;
235                                                         printf("%c\n",UALG.vertices[p->adjvex].data);
236                                                         q.push(p->adjvex);
237                                                }
238                                                p=p->nextarc;
239                                      }
240  
241  
242                             }
243  
244                    }
245  
246 }
247  
248  
249  
250 void prim(MGraph G,char v)
251 {//用prim算法求最小生成树
252          int i,j,k,min,n;
253          k=locatevex(G,v);
254          for(i=0;i<G.vexnum;i++)
255          {
256                    if(i!=k)
257                    {
258                            
259                              closedge[i].adjvex=v;
260                              closedge[i].lowcost=G.arc[k][i].adj;
261  
262                   }
263          }
264          closedge[k].lowcost=0;
265          for(i=1;i<G.vexnum;i++)
266          {
267                    min=INFINITY;
268                   
269                    for(j=0;j<G.vexnum;j++)
270                    {
271                             if(closedge[j].lowcost!=0&&closedge[j].lowcost<min)
272                             {
273                                      n=j;
274                                      min=closedge[j].lowcost;
275                             }
276                    }
277                             printf("%c %c\n",closedge[n].adjvex,G.vex[n]);
278                             closedge[n].lowcost=0;
279                             for(j=0;j<G.vexnum;j++)
280                                      if(G.arc[n][j].adj<closedge[j].lowcost&&G.arc[n][j].adj!=INFINITY)
281                                      {
282                                                closedge[j].adjvex=G.vex[n];
283                                                closedge[j].lowcost=G.arc[n][j].adj;
284                                      }
285                                     
286  
287          }
288          printf("\n");
289  
290  
291 }
292 int indegree[max_vertex_num];
293 int topsort(ALGraph  ALG,ALGraph InsertALG)
294 {//拓扑排序
295          ArcNode *p;
296          stack<int>s;
297          int i,k,count;
298          for(i=0;i<ALG.vexnum;i++)
299          {
300              InsertALG.vertices[i].count=0;
301                    for(p=InsertALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)
302                             InsertALG.vertices[i].count++;
303          }
304          for(i=0;i<ALG.vexnum;i++)
305          {
306                    indegree[i]=InsertALG.vertices[i].count;
307                    printf("%d\n",indegree[i]);
308          }
309  
310          for(i=0;i<ALG.vexnum;i++)
311                    if(indegree[i]==0)
312                             s.push(i);
313                    count=0;
314                    while(!s.empty())
315                    {
316                            
317                             i=s.top();
318                             s.pop();
319                             printf("%c ",ALG.vertices[i].data);
320                             count++;
321                        for(p=ALG.vertices[i].firstarc;p;p=p->nextarc)
322                             {
323                                      k=p->adjvex;
324                                      indegree[k]--;
325                                      if(indegree[k]==0)
326                                                s.push(k);
327                             }
328  
329                   
330                    }
331                    if(count<ALG.vexnum)
332                             return -1;
333                    else
334                             return 1;
335  
336  
337 }
338  
339 void short_dij(MGraph G,int v0,int *P,int *D)
340 {//用dij球最短路径
341          int i,v,w,min;
342          for(i=0;i<G.vexnum;i++)
343          {
344                    finial[i]=0;
345                    D[i]=G.arc[v0][i].adj;
346                    if(D[i]<INFINITY)
347                             P[i]=v0;
348          }
349          D[v0]=0;finial[v0]=1;
350          for(i=1;i<G.vexnum;i++)
351          {
352                    min=INFINITY;
353                    for(w=0;w<G.vexnum;w++)
354                    {
355                             if(finial[w]==0)
356                                      if(D[w]<min)
357                                      {
358                                                v=w;
359                                                min=D[w];
360                                      }
361                    }
362                    if(min<INFINITY)
363                             finial[v]=1;
364                    else
365                             break;
366                    for(w=0;w<G.vexnum;w++)
367                    {
368                             if(finial[w]==0&&min+G.arc[v][w].adj<D[w])
369                             {
370                                      D[w]=min+G.arc[v][w].adj;
371                                      P[w]=v;
372                                      printf("%d ",P[w]);
373                             }
374  
375                    }
376                    printf("\n");
377  
378          }
379          printf("路径长度为:\n");
380          for(i=0;i<G.vexnum;i++)
381          {
382                    if(D[i]==INFINITY)
383                             printf("无法到达!!!\n");
384                    else
385                             printf("%d\n",D[i]);
386          }
387  
388 }
389  
390 int main()
391 {
392          int menu;
393          char V;
394         
395          do{
396                    void print();
397                    scanf("%d",&menu);
398                    switch(menu)
399                    {
400                    case 1: CreateALGraph(ALG,InsertALG);break;
401                    case 2: shuchu(ALG); break;
402         case 3: CreateALGraph(ALG,InsertALG);Degree( ALG, InsertALG);break;
403                    case 4: CreateALGraph(ALG,InsertALG);topsort( ALG,InsertALG);break;
404                    case 5: CeratUALGraph(UALG);DFSTraverse(UALG);break;
405                    case 6: CeratUALGraph(UALG);BFSTraverse(UALG);break;
406                    case 7: CreateUDN(G,1);printf("请输入出发顶点:\n");scanf("%c",&V);prim(G,V);break;
407                    case 8: CreateUDN(G,0);short_dij( G, 0,P,D);break;
408                    case 0: return 0;
409                    }
410          }while(menu!=0);
411          return 0;
412 }
图的基本操作

 七、排序的基本操作

  1 // 实验八:排序的基本操作
  2  
  3 输入一组关键字序列分别实现下列排序:
  41)实现简单选择排序、直接插入排序和冒泡排序。
  52)实现希尔排序算法。
  63)实现快速排序算法。
  74)实现堆排序算法。
  85)采用链式存储实现简单选择排序、直接插入排序和冒泡排序。
  96)在主函数中设计一个简单的菜单,分别测试上述算法。
 10  
 11 综合训练:采用几组不同数据测试各个排序算法的性能(比较次数和移动次数)。
 12  
 13  
 14 # include <stdio.h>
 15 # include <stdlib.h>
 16  
 17 #define MAXSIZE 20
 18 typedef int KeyType;
 19  
 20 typedef struct
 21 {
 22          KeyType key;
 23          //InfoType otherinfo;
 24 }RedType;
 25 typedef struct
 26 {
 27          RedType r[MAXSIZE+1];
 28          int length;
 29 }SqList;
 30  
 31 typedef SqList HeapType;
 32  
 33 typedef struct Node
 34 {
 35          int data;
 36          struct Node * pNext;
 37 }Node, *pNode;
 38  
 39 void printMenu();
 40 void InsertSort(SqList &);
 41 bool LT(int ,int );
 42 void traverse(SqList &);
 43 void SelectSort(SqList &);
 44 int SelectMinKey(SqList &, int);
 45 void BubbleSort(SqList &);
 46 void ShellSort(SqList &L, int dlta[], int t);
 47 void ShellInsert(SqList &L, int);
 48 void Qsort(SqList &, int ,int);
 49 int Partition(SqList &, int ,int);
 50 void HeapSort(HeapType &);
 51 void HeapAdjust(HeapType &, int ,int );
 52 void Ltraverse(pNode &);
 53 void LSelectSort(pNode &);
 54 pNode LSelectMinkey(pNode &);
 55 void LBubbleSort(pNode &);
 56  
 57 int main()
 58 {
 59          int n;
 60          SqList L;
 61          pNode pHead, p, q;
 62          if( !(pHead=(pNode)malloc(sizeof(Node)) ))
 63                    exit (-1);
 64          pHead->pNext = NULL;
 65          int dlta[99] = {3, 2, 1};
 66          printf("请输入数组长度L.length = ");
 67          scanf("%d", &L.length);
 68          p = pHead;
 69          for(int i=1; i<=L.length; i++)
 70          {
 71                    scanf("%d", &L.r[i].key);
 72                    if( !(q = (pNode)malloc(sizeof(Node))))
 73                             exit (-1);
 74                    q->data = L.r[i].key;
 75                    p->pNext = q;
 76                    p = q;
 77          }
 78          p->pNext = NULL;
 79  
 80  
 81          printMenu();
 82          while(scanf("%d", &n)!=EOF)
 83          {
 84                    switch(n)
 85                    {
 86                    case 1:
 87                             SelectSort(L);
 88                             printf("---排序后的数组为:");
 89                             traverse(L);
 90                             break;
 91                    case 2:
 92                             InsertSort(L);
 93                             printf("---排序后的数组为:");
 94                             traverse(L);
 95                             break;
 96                    case 3:
 97                             BubbleSort(L);
 98                             printf("---排序后的数组为:");
 99                             traverse(L);
100                             break;
101                    case 4:
102                             ShellSort(L, dlta, 2);
103                             printf("---排序后的数组为:");
104                             traverse(L);
105                             break;
106  
107                    case 5:
108                            
109                             Qsort(L, 1, L.length);
110                             printf("---排序后的数组为:");
111                             traverse(L);
112                             break;
113                    case 6:
114                             HeapSort(L);
115                             printf("---排序后的数组为:");
116                             traverse(L);
117                             break;
118                    case 7:
119                             LSelectSort(pHead);
120                             Ltraverse(pHead);
121                             break;
122  
123                    case 8:
124                             BubbleSort(L);
125                             traverse(L);
126                             break;
127                    case 9:
128                             LBubbleSort(pHead);
129                             Ltraverse(pHead);
130                             break;
131                   
132                    default:
133                             printf("---输入有误,请重新输入!!---\n");
134                    }
135                    printMenu();
136          }
137  
138  
139          return 0;
140 }
141  
142 void printMenu()
143 {
144          printf("------排序菜单如下------\n");
145          printf("1.简单选择排序\n");
146          printf("2.直接插入排序\n");
147          printf("3.冒泡排序\n");
148  
149          printf("4.希尔排序\n");
150          printf("5.快速排序\n");
151          printf("6.堆排序\n");
152          printf("7.链式存储实现简单选择排序\n");
153          printf("8.链式存储实现简单直接插入排序\n");
154          printf("9.链式存储实现简单冒泡排序\n");
155          printf("---请选择排序方式:");
156 }
157  
158 void InsertSort(SqList &L)
159 {
160          int i, j;
161          for( i=2; i<=L.length; i++)
162                    if(LT(L.r[i].key, L.r[i-1].key))
163                    {
164                             L.r[0] = L.r[i];
165                             L.r[i] = L.r[i-1];
166                             for( j=i-2; LT(L.r[0].key, L.r[j].key); --j)
167                                      L.r[j+1] = L.r[j];
168                             L.r[j+1] = L.r[0];
169                    }
170 }
171  
172 bool LT(int a,int b)
173 {
174          if( a>=b )
175                    return false;
176          else
177                    return true;
178 }
179  
180 void traverse(SqList &L)
181 {
182          for( int i=1; i<=L.length; i++)
183                    printf("%d ", L.r[i].key);
184          printf("\n\n");
185 }
186  
187 void SelectSort(SqList &L)
188 {
189          int i, j;
190          RedType t;
191          for( i=1; i<=L.length; i++)
192          {
193                    j = SelectMinKey(L, i);
194                    if( i!=j)
195                    {
196                             t = L.r[i];
197                             L.r[i] = L.r[j];
198                             L.r[j] = t;
199                    }
200          }
201 }
202  
203 int SelectMinKey(SqList &L, int j)
204 {
205          int min, k;
206          k = j;
207          min = L.r[k].key;
208          for(int i=j; i<=L.length; i++)
209          {
210                    if( L.r[i].key<min )
211                    {
212                             min = L.r[i].key;
213                             k = i;
214                    }
215          }
216          return k;
217 }
218  
219 void BubbleSort(SqList &L)
220 {
221          int i, j;
222          RedType t;
223          for( i=1; i<L.length; i++)
224                    for( j=i+1; j<=L.length; j++)
225                    {
226                             if(L.r[i].key > L.r[j].key)
227                             {
228                                      t = L.r[i];
229                                      L.r[i] = L.r[j];
230                                      L.r[j] = t;
231                             }
232                    }
233 }
234  
235 void ShellSort(SqList &L, int dlta[], int t)
236 {
237          int k;
238          for(k=0; k<t; k++)
239                    ShellInsert(L, dlta[k]);
240 }
241  
242 void ShellInsert(SqList &L, int dk)
243 {
244          int i, j;
245          for( i=dk+1; i<=L.length; i++)
246                    if(LT(L.r[i].key, L.r[i-dk].key))
247                    {
248                             L.r[0] = L.r[i];
249                             for(j=i-dk; j>0 && LT(L.r[0].key, L.r[j].key); j-=dk)
250                                      L.r[j+dk] = L.r[j];
251                             L.r[j+dk] = L.r[0];
252                    }
253 }
254  
255 void Qsort(SqList &L, int low, int high)
256 {
257          int pivotloc;
258          if(low<high)
259          {
260                    pivotloc = Partition(L, low, high);
261                    Qsort(L, low, pivotloc-1);
262                    Qsort(L, pivotloc+1, high);
263          }
264 }
265  
266 int Partition(SqList &L, int low,int high)
267 {
268          int pivotkey;
269          L.r[0] = L.r[low];
270          pivotkey = L.r[low].key;
271          while(low<high)
272          {
273                    while(low<high && L.r[high].key>=pivotkey)
274                             --high;
275                    L.r[low] = L.r[high];
276                    while(low<high && L.r[low].key<=pivotkey)
277                             ++low;
278                    L.r[high] = L.r[low];
279          }
280          L.r[low] = L.r[0];
281          return low;
282 }
283  
284 void HeapSort(HeapType &H)
285 {
286          int i;
287          RedType t;
288          for( i = H.length/2; i>0; i--)
289                    HeapAdjust( H, i, H.length );
290          for( i = H.length; i>1; i--)
291          {
292                    t = H.r[1];
293                    H.r[1] = H.r[i];
294                    H.r[i] = t;
295                    HeapAdjust(H, 1, i-1);
296          }
297 }
298  
299 void HeapAdjust(HeapType &H, int s,int m)
300 {
301          int j;
302          RedType rc;
303          rc = H.r[s];
304          for( j=2*s; j<=m; j*=2)
305          {
306                    if( j<m && LT(H.r[j].key, H.r[j+1].key) )
307                             j++;
308                    if( !LT(rc.key, H.r[j].key) )
309                             break;
310                    H.r[s] = H.r[j];
311                    s = j;
312          }
313          H.r[s] = rc;
314 }
315  
316 void Ltraverse(pNode &pHead)
317 {
318          pNode p;
319          p = pHead->pNext;
320          while( NULL != p)
321          {
322                    printf("%d ", p->data);
323                    p = p->pNext;
324          }
325          printf("\n");
326 }
327  
328 void LSelectSort(pNode &pHead)
329 {
330          pNode p, q;
331          int t;
332          q = (pNode)malloc(sizeof(Node));
333          for( p = pHead->pNext->pNext; NULL != p->pNext; p = p->pNext)
334          {
335                    q = LSelectMinkey( p );
336                    if( p->data != q->data)
337                    {
338                             t = p->data;
339                             p->data = q->data;
340                             q->data = t;                        
341                    }
342          }
343 }
344  
345 pNode LSelectMinkey(pNode &p)
346 {
347          pNode q;
348          q = p;
349          int min;
350          min = q->data;
351          while( p != NULL)
352          {
353                    if( p->data < min)
354                    {
355                             min = p->data;
356                             q = p;
357                    }
358                    p = p->pNext;
359          }
360  
361          return q;
362 }
363  
364 void LBubbleSort(pNode &pHead)
365 {
366          int  t;
367          pNode p,q;
368          //RedType t;
369          for( p=pHead->pNext;  p->pNext->pNext != NULL;  p = p->pNext)
370                    for( q=p->pNext; q->pNext!=NULL; q=q->pNext)
371                    {
372                             if(p->data > q->data)
373                             {
374                                      t = p->data;
375                                      p->data = q->data;
376                                      q->data = t;
377                             }
378                    }
379 }
排序的基本操作

 

posted @ 2017-07-06 11:00  樱桃挚爱丸子  阅读(538)  评论(0编辑  收藏  举报