最近学计算机软件基础,学到了线性表。下面就将线性表中最简单的顺序表的一个简单示例贴出,方便大家探讨。(以及后面对函数传参的一个小分析,其实这才是重点)
1 ////需求分析 2 //1、线性表递增有序,删除重复元素 3 //2、线性表逆置 4 //3、寻求最大值 5 6 #include<stdio.h> 7 8 typedef int ElementType; 9 typedef struct _struct 10 { 11 ElementType SequenceList[100]; 12 ElementType num; 13 }SequenceList; 14 15 void InitSeq(SequenceList **L);//初始化线性表,主要是返回一个SequenceList实例,采用malloc动态开辟内存方式。 16 int Add(SequenceList *L, ElementType value);//想列表中添加项目 17 void Insert(SequenceList *L ,ElementType pos, ElementType value);//插入一个元素 18 void Delete(SequenceList *L, ElementType value);//删除一个元素 19 ElementType Search(SequenceList *L, ElementType value);//搜索一个元素 20 void RemoveRepetiton(SequenceList *L);//移除所有重复的元素 21 void Transpose(SequenceList *L);//将所有元素位置倒置 22 ElementType MaxValue(SequenceList *L);//求出元素中最大值 23 void Travel(SequenceList *L);//遍历整个列表(把每个元素都输出一遍) 24 25 int main() 26 { 27 SequenceList *L; 28 InitSeq(&L); 29 while (1) 30 { 31 int n = 0; 32 int pos; 33 ElementType value; 34 printf("请选择操作:(1.Add 2.insert 3.delete 4.search 5.transpose 6.maxium 7.travel 8.removeReptitons)\n"); 35 scanf("%d", &n); 36 switch (n) 37 { 38 //add 39 case 1: 40 41 printf("添加新项:"); 42 scanf("%d", &value); 43 Add(L, value); 44 break; 45 //insert 46 case 2: 47 48 printf("选择位置插入一项:(位置 值)\n"); 49 scanf("%d %d", &pos,&value); 50 Insert(L,pos, value); 51 break; 52 //delete: 53 case 3: 54 printf("输入删除内容:"); 55 scanf("%d", &value); 56 Delete(L, value); 57 break; 58 //Search 59 case 4: 60 printf("搜索内容:"); 61 scanf("%d", &value); 62 pos = Search(L, value); 63 if (pos) 64 printf("存在于第%d项。\n", pos); 65 else 66 printf("无法找到!\n"); 67 break; 68 //transpose: 69 case 5: 70 Transpose(L); 71 Travel(L); 72 break; 73 //max 74 case 6: 75 printf("最大值是%d。\n", MaxValue(L)); 76 break; 77 case 7: 78 Travel(L); 79 break; 80 case 8: 81 RemoveRepetiton(L); 82 break; 83 default: 84 break; 85 } 86 } 87 free(L); 88 return 0; 89 } 90 void InitSeq(SequenceList **L) 91 { 92 *L = (SequenceList *)malloc(sizeof(SequenceList)); 93 (*L)->num = -1; 94 } 95 96 int Add(SequenceList *L, ElementType value) 97 { 98 L->num++; 99 if (L->num >= 100) 100 { 101 L->num--; 102 printf("空间已满!"); 103 return 0; 104 } 105 L->SequenceList[L->num] = value; 106 return 1; 107 } 108 109 void Insert(SequenceList *L, ElementType pos, ElementType value) 110 { 111 if (L->num<0||L->num >= 99) 112 { 113 printf("空间已满或不足!"); 114 return 0; 115 } 116 if (pos-1 < 0 || pos-1 > L->num) 117 { 118 printf("插入位置错误!"); 119 return; 120 } 121 int i; 122 for (i = L->num; i >= pos-1; i--) 123 { 124 L->SequenceList[i+1] = L->SequenceList[i]; 125 } 126 L->SequenceList[pos - 1] = value; 127 L->num++; 128 } 129 130 void Delete(SequenceList *L, ElementType value) 131 { 132 if (L->num < 0) 133 { 134 printf("表为空!"); 135 return; 136 } 137 int i; 138 for (i = 0; i <= L->num; i++) 139 { 140 if (value == L->SequenceList[i]) 141 { 142 int j; 143 for (j = i; j < L->num; j++) 144 { 145 L->SequenceList[j] = L->SequenceList[j + 1]; 146 } 147 L->num--; 148 } 149 } 150 } 151 152 ElementType Search(SequenceList *L, ElementType value) 153 { 154 if (L->num<0) 155 { 156 printf("表空!"); 157 return -1; 158 159 } 160 else 161 { 162 int i; 163 for (i = 0; i <= L->num; i++) 164 { 165 if (value == L->SequenceList[i]) 166 return i + 1; 167 } 168 } 169 170 return 0; 171 } 172 173 void RemoveRepetiton(SequenceList *L) 174 { 175 int count=0; 176 int i; 177 for (i = 0; i <= L->num; i++) 178 { 179 if (Search(L, L->SequenceList[i])) 180 { 181 Delete(L, L->SequenceList[i]); 182 count++; 183 } 184 } 185 printf("共删除了%d项。", count); 186 } 187 188 void Transpose(SequenceList *L) 189 { 190 ElementType *temp = (ElementType *)malloc(sizeof(ElementType)*(L->num + 1)); 191 int i ,j; 192 for (i = L->num, j = 0; i >= 0; i--,j++) 193 { 194 temp[j] = L->SequenceList[i]; 195 } 196 for (i = 0; i <= L->num; i++) 197 { 198 L->SequenceList[i] = temp[i]; 199 } 200 free(temp); 201 } 202 ElementType MaxValue(SequenceList *L) 203 { 204 int i = 0; 205 ElementType max = L->SequenceList[0]; 206 for (i = 1; i <= L->num; i++) 207 { 208 if (max < L->SequenceList[i]) 209 { 210 max = L->SequenceList[i]; 211 } 212 } 213 return max; 214 } 215 216 void Travel(SequenceList *L) 217 { 218 if (L->num < 0) 219 printf("表空!"); 220 else 221 { 222 int i; 223 for (i = 0; i <= L->num; i++) 224 { 225 printf("%d ", L->SequenceList[i]); 226 if (i>0&&(i % 10 == 0)) 227 printf("\n"); 228 } 229 printf("\n"); 230 } 231 }
点击查看代码
代码纯手打,不是网上copy过来的。。
代码中没什么算法,搜索、删除等都用的最简单的方式。
代码中唯一值得注意的就是初始化列表的函数InitList(SequenceList **L),传的是二级指针做参数,为什么这么做呢?
下面解释一下:
我们的目的是在函数InitList中malloc一块内存空间,用于存放我们的数据。
现在先看我们常写的一个错误写法
//请看如下错误代码,这是为说明问题的错误代码 void InitList(SequenceList *L) { L=(SequenceList *)malloc(sizeof(SequenceList));//语法重点。。 L->num=-1;//这个是程序功能的一部分 }
许多的初学者认为我们传到函数InitList中的是一个指针变量,在InitList中可以对该指针变量进行赋值操作,以便达到修改主函数中变量的目的,于是乎便将malloc开辟的空间首地址赋给L,然后在主函数中对L操作的时候发现要么是乱码,要么是不可访问之类的错误,百思不得其解,为什么呢?
原因很简单,就是对函数参数的传递方式不明确造成的。在此处应该记着,函数传参始终是将你所传变量复制后的副本传进去,并不是该变量本身。
代入这个实际问题,我们在主函数中做如下操作
//为错误情况的示例代码,切记void main() { SequenceList *L; InitList(L); ...... }
我们为函数InitList传递的是一个SequenceList类型的指针变量L,假设L此时指向内存0x10000,则在实际传参数的时候,系统会对L变量作一个复制操作,假设这儿使复制后的变量为P,则P指向的地址也为L指向的地址0x10000。
现在重点来了,我们为InitList传递参数L,但系统实际传递的参数是P(P是L的副本,他们指向同一块内存区域,但他们各自的地址不同),在函数InitList内部,则实际是对P变量进行操作,把malloc的地址(假设为0x30000)赋值给P,
所以P指向的地址是0x30000,但是主函数中的L仍然指向0x10000,所以就造成了我们遇见的错误,因为我们根本没有把L指向的地址改为malloc的地址;
那么接下来看正确的操作。
//以下代码为正确代码 void main() { SequenceList *L; InitList(&L); } void InitSeq(SequenceList **L) { *L = (SequenceList *)malloc(sizeof(SequenceList)); (*L)->num = -1; }
我们传参数的时候传的是变量L的地址,那么系统实际传的是变量P,P与L有如下关系:P=&L(P指向变量L的地址).在函数InitList中
*L = (SequenceList *)malloc(sizeof(SequenceList));
L是P,*L即是主函数中的L,现在用malloc的地址给*L,就实现了为主函数中L赋值的操作。
明白了吗?这是我个人的理解。可能系统在某些细节上和我说的不一样,但我这个思路应该是没错的。