文字描述:
为了表示前后两个数据元素的逻辑关系,对于每个数据元素,除了存储其本身的信息之外(数据域),还需存储一个指示其直接后继的信息(即直接后继的存储位置,指针域)。
示意图:
算法分析:
在单链表中插入和删除元素时,主要是改变指针的值,其时间复杂度为1。而顺序存储的话,其时间复杂度为n。
在单链表中求长度时不如顺序存储结构,其时间复杂度为n; 而顺序存储是1。故可以在链表头结点中设置一个长度值,在插入数据元素时加1,在删除数据元素时减1。
在单链表中查找指定数据元素时,其时间复杂度和顺序存草时一样,乱序情况下为n。
代码实现(动态单链表):
1 // 2 // Created by lady on 19-1-26. 3 // 4 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <string.h> 8 9 //线性表的动态单链表存储结构 10 typedef struct ElemType{ 11 char data[10]; 12 }ElemType; 13 typedef struct LNode{ 14 ElemType e; 15 struct LNode *next; 16 }LNode, *LinkList; 17 18 /* 19 * 倒序法输入n个元素的值,建立带表头结点的单链表线性表L 20 */ 21 static int CreateList_L(LinkList *L, int n, char name[]) 22 { 23 printf("以倒插入法创建单链表存储结构的线性表%s: ", name); 24 //先建立一个带头结点的单链表 25 if((*L=(LinkList)malloc(sizeof(LNode))) == NULL){ 26 return -1; 27 } 28 (*L)->next = NULL; 29 int i = 0; 30 LinkList p = NULL; 31 for(i=n; i>0; --i){ 32 //生成新的结点 33 p = (LinkList)malloc(sizeof(LNode)); 34 //输入元素值 35 printf("输入第%d个元素:", i); 36 scanf("%s[^\n]", p->e.data); 37 //插入到表头 38 p->next = (*L)->next; 39 (*L)->next = p; 40 } 41 return 0; 42 } 43 44 /*依次对L的每个数据元素调用函数fun。一旦fun失败,则操作失败*/ 45 static int ListTraverse_L(LinkList L, int (*fun)(ElemType,int), char info[]) 46 { 47 printf("%s", info); 48 //跳过头结点 49 LNode *p = L->next; 50 int i = 1; 51 while(p){ 52 if(fun(p->e, i++)){ 53 printf("Err:when traverse(e,%d) wrong! ",i); 54 } 55 p = p->next; 56 } 57 printf(" "); 58 } 59 60 /* 61 * L为带头结点的单链表的头指针 62 * 当第i个元素存在是,其值赋给e并返回0,否则返回-1 63 */ 64 static int GetElem_L(LinkList L, int i, ElemType *e) 65 { 66 //初始化,p指向第一个结点 67 LNode *p = L->next; 68 //j为计数器 69 int j = 1; 70 while(p && j<i){ 71 //顺指针向后查找,知道p指向第i个元素或者p为空 72 p = p->next; 73 j+=1; 74 } 75 if(!p || j>i){ 76 //第i个元素不存在 77 return -1; 78 } 79 //取第i个元素 80 *e = p->e; 81 return 0; 82 } 83 84 /* 85 * 在带头结点的单链表线性表L中第i个位置之前插入元素e 86 */ 87 static int ListInsert_L(LinkList *L, int i, ElemType e) 88 { 89 LNode *p = (LNode *)(*L); 90 int j = 0; 91 while(p && j<i-1){ 92 //寻找第i-1个结点 93 p = p->next; 94 ++j; 95 } 96 //i小于1或者大于表长+1 97 if(!p || j>i) 98 return -1; 99 //生成新的结点 100 LinkList s = (LinkList)malloc(sizeof(LNode)); 101 s->e = e; 102 //将新结点插入到链表L中 103 s->next = p->next; 104 p->next = s; 105 return 0; 106 } 107 108 /* 109 * 在带头结点的单链线性表L中,删除第i个元素,并有e返回其值 110 */ 111 static int ListDelete_L(LinkList *L, int i, ElemType *e) 112 { 113 LNode *p = (LNode *)(*L); 114 LNode *q = NULL; 115 int j = 0; 116 while(p->next && (j<i-1)){ 117 //寻找第i个结点,并令p指向其前趋 118 p = p->next; 119 ++j; 120 } 121 if(!(p->next) || (j>i-1)){ 122 //删除位置不合理 123 return -1; 124 } 125 //删除该结点 126 q = p->next; 127 p->next = q->next; 128 *e = q->e; 129 //释放该结点的占用空间 130 free(q); 131 return 0; 132 } 133 134 /* 135 * 输入元素e的数据和位置 136 */ 137 static int printE(ElemType e, int location) 138 { 139 printf("%3d=%-10s", location, e.data); 140 return 0; 141 } 142 143 /* 144 * 已知单链线性表La和Lb的元素按值非递减排列 145 * 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列 146 */ 147 static void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) 148 { 149 LNode *pa = La->next; 150 LNode *pb = Lb->next; 151 LNode *pc = NULL; 152 LNode *p; 153 //用La的头结点作为Lc的头结点 154 pc = (LNode*)La; 155 *Lc = La; 156 157 while(pa && pb){ 158 if(atoi(pa->e.data) <= atoi(pb->e.data)){ 159 //需要将当前的pa结点插入到pc结点 160 if(pc->next == pa){ 161 //pc结点正好在pa链表 162 pc = pc->next;//移动pc结点到下一个结点 163 pa = pa->next;//移动pa结点到下一个结点 164 }else{ 165 //需要将pa结点插入到pc结点后,插入后pc、pa结点要后移动 166 p = pa; 167 pa = pa->next; 168 p->next = pc->next; 169 pc->next = p; 170 pc = pc->next; 171 } 172 }else{ 173 if(pc->next == pb){ 174 pc = pc->next; 175 pb = pb->next; 176 } else{ 177 p = pb; 178 pb = pb->next; 179 p->next = pc->next; 180 pc->next = p; 181 pc = pc->next; 182 } 183 } 184 } 185 //插入剩余段 186 pc->next = pa?pa:pb; 187 //释放Lb的头结点 188 free(Lb); 189 } 190 191 /* 192 * 释放链表L 193 */ 194 static int DestoryList_L(LinkList *L) 195 { 196 if(L == NULL){ 197 return -1; 198 } 199 if(*L == NULL){ 200 return -1; 201 } 202 LNode *p, *q; 203 p = (LNode*)(*L); 204 while(p){ 205 q = p; 206 free(q); 207 p = p->next; 208 } 209 *L = NULL; 210 return 0; 211 } 212 213 int main(int argc, char *argv[]) 214 { 215 216 ElemType e; 217 int location = 0; 218 219 LinkList L; 220 CreateList_L(&L, 4, "L"); 221 ListTraverse_L(L, printE, "L:"); 222 223 printf("insert a data and print, please input (location, data):"); 224 scanf("%d,%s[^\n]", &location, e.data); 225 ListInsert_L(&L, location, e); 226 ListTraverse_L(L, printE, "L:"); 227 printf(" "); 228 229 printf("delete a data through location and print, please input (location):"); 230 scanf("%d[^\n]", &location); 231 ListDelete_L(&L, location, &e); 232 printf("location %d, data %s is deleted from List ", location, e.data); 233 ListTraverse_L(L, printE, "init:"); 234 printf(" "); 235 236 printf("locate/find a data through location, please input (location):"); 237 scanf("%d[^\n]", &location); 238 GetElem_L(L, location, &e); 239 printf("the data of what location is %d, is %s ", location, e.data); 240 printf(" "); 241 242 printf("Merge LA and LB to LC! "); 243 LinkList La, Lb, Lc; 244 //create La 245 CreateList_L(&La, 4, "La"); 246 ListTraverse_L(La, printE, "La:"); 247 //create Lb 248 CreateList_L(&Lb, 7, "Lb"); 249 ListTraverse_L(Lb, printE, "Lb:"); 250 //merge La and Lb to Lc 251 MergeList_L(La, Lb, &Lc); 252 ListTraverse_L(Lc, printE, "Lc:"); 253 254 DestoryList_L(&L); 255 DestoryList_L(&La); 256 DestoryList_L(&Lb); 257 }
代码运行(动态单链表):
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 以倒插入法创建单链表存储结构的线性表L: 输入第4个元素:ZHAO 输入第3个元素:QIAN 输入第2个元素:SUN 输入第1个元素:LI L: 1=LI 2=SUN 3=QIAN 4=ZHAO insert a data and print, please input (location, data):2,ZHOU L: 1=LI 2=ZHOU 3=SUN 4=QIAN 5=ZHAO delete a data through location and print, please input (location):3 location 3, data SUN is deleted from List init: 1=LI 2=ZHOU 3=QIAN 4=ZHAO locate/find a data through location, please input (location):3 the data of what location is 3, is QIAN Merge LA and LB to LC! 以倒插入法创建单链表存储结构的线性表La: 输入第4个元素:11 输入第3个元素:8 输入第2个元素:5 输入第1个元素:3 La: 1=3 2=5 3=8 4=11 以倒插入法创建单链表存储结构的线性表Lb: 输入第7个元素:20 输入第6个元素:15 输入第5个元素:11 输入第4个元素:9 输入第3个元素:8 输入第2个元素:6 输入第1个元素:2 Lb: 1=2 2=6 3=8 4=9 5=11 6=15 7=20 Lc: 1=2 2=3 3=5 4=6 5=8 6=8 7=9 8=11 9=11 10=15 11=20 Process finished with exit code 0
代码实现(带头结点的单向动态链表)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 //带头结点的线性链表类型定义如下 6 typedef struct ElemType{ 7 char data[10]; 8 }ElemType; 9 typedef struct LNode{//结点类型 10 ElemType e; 11 struct LNode *next; 12 }*Link, *Position; 13 typedef struct {//链表类型 14 Link head,tail;//分别指向线性链表中的头结点和最后一个结点 15 int len;//指示线性链表中数据元素的个数 16 }LinkList; 17 18 /* 19 *依次对L的每个元素调用visit函数,一旦失败,则操作失败 20 */ 21 static int ListTraverse(LinkList L, int (*visit)(ElemType,int), const char note[]) 22 { 23 printf("遍历线性表%s:", note); 24 Link p = L.head->next; 25 int i = 1; 26 while(p){ 27 if(visit(p->e,i)<0){ 28 return -1; 29 } 30 if(p==L.tail) 31 break; 32 p = p->next; 33 } 34 printf(" "); 35 return 0; 36 } 37 38 static int print(ElemType e, int loc) 39 { 40 printf("%3d=%-6s", loc, e.data); 41 return 0; 42 } 43 44 //构造一个空的线性链表L 45 static int InitList(LinkList *L) 46 { 47 if(L==NULL){ 48 return -1; 49 } 50 Link p = (Link)malloc(sizeof(struct LNode)); 51 memset(p->e.data, 0, sizeof(p->e.data)); 52 p->next = p; 53 L->len = 0; 54 L->head = L->tail = p; 55 return 0; 56 } 57 58 //返回p指示线性链表L中第i个结点的位置并返回0 i值不合法时返回-1 59 static int LocatePos(LinkList *L, int i, Link *p) 60 { 61 if(L==NULL || p==NULL){ 62 return -1; 63 } 64 *p=L->head; 65 int index = 0; 66 while((index<L->len) && (*p != L->tail)){ 67 (*p) = (*p)->next; 68 index +=1; 69 if(index == i) 70 break; 71 } 72 return (index==i)?0:-1; 73 } 74 75 //创建一个值为e的结点, 其地址为p; 成功则返回0, 失败就返回-1 76 static int MakeNode(Link *p, ElemType e) 77 { 78 if(p==NULL){ 79 return -1; 80 } 81 if(((*p) = (Link)malloc(sizeof(struct LNode))) == NULL){ 82 return -1; 83 } 84 (*p)->next = NULL; 85 (*p)->e = e; 86 return 0; 87 } 88 89 //已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前 90 static int InsFirst(Link *h, Link *s) 91 { 92 if(h==NULL || s==NULL){ 93 return -1; 94 } 95 if(*h == NULL || *s == NULL){ 96 return -1; 97 } 98 (*s)->next = (*h)->next; 99 (*h)->next = (*s); 100 return 0; 101 } 102 103 //在带头结点的单链线性表L的第i个元素之前插入元素e 104 static int ListInsert_L(LinkList *L, int i, ElemType e) 105 { 106 Link h = NULL; 107 Link p = NULL; 108 if(LocatePos(L, i-1, &h)<0){ 109 //i值不合法 110 return -1; 111 } 112 if(MakeNode(&p, e)<0){ 113 //结点存储分配失败 114 return -1; 115 } 116 //对于从第i个结点开始的链表,第i-1个结点是它的头结点 117 InsFirst(&h, &p); 118 //如果是在链表的最后一个结点上插入, 那么和改变链表的尾结点指针 119 if(L->tail == h){ 120 p->next = L->head; 121 L->tail = p; 122 } 123 //链表长度+1 124 L->len += 1; 125 return 0; 126 } 127 128 //创建一个长度为n的带头结点的单项链表L 129 static int CreateList(LinkList *L, int n, char note[]) 130 { 131 printf("创建一个长度为%d的带头结点的单向线性链表%s! ", n, note); 132 if(L==NULL){ 133 return -1; 134 } 135 if(InitList(L)<0){ 136 return -1; 137 } 138 ElemType e; 139 int i = 0; 140 for(i=1; i<=n; i++){ 141 printf("输入第%d个元素:", i); 142 scanf("%s[^\n]", e.data); 143 if(ListInsert_L(L, i, e)<0){ 144 return -1; 145 } 146 } 147 } 148 149 //返回链表L的头结点 150 static Link GetHead(LinkList *L){ 151 if(L==NULL){ 152 return NULL; 153 } 154 return L->head; 155 } 156 157 //返回链表L中结点p的后继 158 static Link NextPos(LinkList *L, Link p) 159 { 160 if(L == NULL || p==NULL){ 161 return NULL; 162 } 163 return p->next; 164 } 165 166 //返回结点p中的数据元素 167 static ElemType GetCurElem(Link p) 168 { 169 return p->e; 170 } 171 172 //释放结点p 173 static void FreeNode(Link p) 174 { 175 if(p) 176 free(p); 177 return; 178 } 179 180 //将指针s所指的一串结点连接到线性链表L的最后一个结点 181 static int Append(LinkList *L, Link *s) 182 { 183 if(L == NULL || s==NULL || *s==NULL){ 184 return -1; 185 } 186 L->tail->next = (*s); 187 Link p = *s; 188 Link t = p; 189 int count = 0; 190 while(p){ 191 count += 1; 192 t = p; 193 p = p->next; 194 } 195 L->len += count; 196 t->next = L->head; 197 L->tail = t; 198 return 0; 199 } 200 201 //已知h指向线性链表的头结点,删除链表中的第一个结点并以求返回 202 static int DelFirst(Link *h, Link *q) 203 { 204 if(h==NULL || q==NULL){ 205 return -1; 206 } 207 if(*h == NULL || *q == NULL){ 208 return -1; 209 } 210 (*q) = (*h)->next; 211 (*h)->next = (*q)->next; 212 (*q)->next = NULL; 213 return 0; 214 } 215 216 //已知单链线性表La和Lb的元素按值非递减排列 217 //归并La和Lb得到新的单链线性表Lc Lc的元素也按值非递减排列 218 static int MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int (*compare)(ElemType,ElemType),const char note[]) 219 { 220 printf("%s ", note); 221 if(InitList(Lc)<0){ 222 //存储空间分配失败 223 return -1; 224 } 225 Link ha = GetHead(La);//ha指向La的头结点 226 Link hb = GetHead(Lb);//hb指向Lc的头结点 227 if(ha==NULL || hb==NULL){ 228 return -1; 229 } 230 Link pa = NextPos(La, ha);//pa指向La中第一个结点 231 Link pb = NextPos(Lb, hb);//pb指向Lb中第一个结点 232 Link p; 233 234 ElemType a; 235 ElemType b; 236 237 Link q; 238 while(pa && pb){ 239 //La和Lb均非空 240 //a和b为两表中当前比较元素 241 a = GetCurElem(pa); 242 b = GetCurElem(pb); 243 if(compare(a, b)<=0){//a<=b 244 DelFirst(&ha, &q); 245 Append(Lc, &q); 246 if(pa == La->tail){ 247 pa = NULL; 248 break; 249 } 250 pa = NextPos(La, ha); 251 }else{//a>b 252 DelFirst(&hb, &q); 253 Append(Lc, &q); 254 if(pb == Lb->tail){ 255 pb = NULL; 256 break; 257 } 258 pb = NextPos(Lb, hb); 259 } 260 } 261 if(pa){ 262 //链接La中剩余结点 263 p = pa; 264 while(p){ 265 if(p == La->tail){ 266 p->next = NULL; 267 break; 268 } 269 p = p->next; 270 } 271 Append(Lc, &pa); 272 }else{ 273 //链接Lb中剩余结点 274 p = pb; 275 while(p){ 276 if(p == Lb->tail){ 277 p->next = NULL; 278 break; 279 } 280 p = p->next; 281 } 282 Append(Lc, &pb); 283 } 284 //释放La和Lb的头结点 285 FreeNode(ha); 286 FreeNode(hb); 287 return 0; 288 } 289 290 /* 291 * 将元素a和b转换成整数a和整数b 292 * 返回-1:整数a > 整数b 293 * 返回0:整数a = 整数b 294 * 返回1:整数a < 整数b 295 */ 296 static int compare(ElemType a, ElemType b) 297 { 298 int i_a = atoi(a.data); 299 int i_b = atoi(b.data); 300 if(i_a<i_b){ 301 return -1; 302 }else if(i_a == i_b){ 303 return 0; 304 }else{ 305 return 1; 306 } 307 } 308 309 int main(int argc, char *argv[]) 310 { 311 LinkList La; //3,5,8,11 312 LinkList Lb; //2,6,8,9,11,15,20 313 if((CreateList(&La, 4, "La")<0) || (ListTraverse(La, print, "La")<0)){ 314 return -1; 315 } 316 if((CreateList(&Lb, 7, "Lb")<0) || (ListTraverse(Lb, print, "Lb")<0)){ 317 return -1; 318 } 319 LinkList Lc; 320 if((MergeList_L(&La, &Lb, &Lc, compare, "归并La和Lb到Lc!")<0) || (ListTraverse(Lc, print, "Lc")<0)){ 321 return -1; 322 } 323 return 0; 324 }
代码运行(带头结点的单向动态链表)
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 创建一个长度为4的带头结点的单向线性链表La! 输入第1个元素:3 输入第2个元素:5 输入第3个元素:8 输入第4个元素:11 遍历线性表La: 1=3 1=5 1=8 1=11 创建一个长度为7的带头结点的单向线性链表Lb! 输入第1个元素:2 输入第2个元素:6 输入第3个元素:8 输入第4个元素:9 输入第5个元素:11 输入第6个元素:15 输入第7个元素:20 遍历线性表Lb: 1=2 1=6 1=8 1=9 1=11 1=15 1=20 归并La和Lb到Lc! 遍历线性表Lc: 1=2 1=3 1=5 1=6 1=8 1=8 1=9 1=11 1=11 1=15 1=20 Process finished with exit code 0
代码实现(静态单链表):
1 // 2 // Created by lady on 19-1-27. 3 // 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 //---------------线性表的静态单链表存储结构----------- 10 #define MAXSIZE 12 //链表的最大长度 11 typedef struct ElemType{ 12 char data[10]; 13 }ElemType; 14 typedef struct{ 15 ElemType e; 16 int cur; 17 }component,SLinkList[MAXSIZE]; 18 19 /* 20 * 依次打印静态链表space中的数据 21 */ 22 static void Debug_Print(SLinkList space, char note[]) 23 { 24 printf("%s ", note); 25 int i = 0; 26 for(i=0; i<MAXSIZE; i++){ 27 printf(" index %-5d[data:%-5s,cur:%-2d] ", i, space[i].e.data, space[i].cur); 28 } 29 } 30 31 /* 32 * 将一维数组space中各分量链成一个备用链表,space[0].cur为头指针, “0”表示空指针。 33 */ 34 static void InitSpace_SL(SLinkList space) 35 { 36 int i = 0; 37 for(i=0; i<MAXSIZE-1; ++i){ 38 memset(space[i].e.data, 0, sizeof(space[i].e.data)); 39 space[i].cur = i+1; 40 } 41 memset(space[MAXSIZE-1].e.data, 0, sizeof(space[MAXSIZE-1].e.data)); 42 space[MAXSIZE-1].cur = 0; 43 return ; 44 } 45 46 /* 47 * 如果备用空间链表非空,则返回分配的结点下标,否则返回0 48 */ 49 static int Malloc_SL(SLinkList space) 50 { 51 int i = 0; 52 i = space[0].cur; 53 if(space[0].cur) 54 space[0].cur = space[i].cur; 55 return i; 56 } 57 58 /* 59 * 将下标为k的空闲结点回收到备用链表。 60 */ 61 static int Free_SL(SLinkList space, int k) 62 { 63 space[k].cur = space[0].cur; 64 space[0].cur = k; 65 return 0; 66 } 67 68 /* 69 * 依次输入集合A和B的元素,在一维数组space中建立表示集合 (A-B)U(B-A)的静态链表,S为其头指针。 70 * 假设备用空间够大,space[0].cur为备用空间的头指针 71 */ 72 static void difference(SLinkList space, int *S) 73 { 74 printf("用静态链表算集合(A-B)U(B-A): "); 75 InitSpace_SL(space); //将space整个初始化成备用空间 76 (*S) = Malloc_SL(space);//生成S的头结点 77 int r = *S;//r始终指向静态链表S的最后一个元素。 78 int m, n; 79 int i, j; 80 char str[128] = {0}; 81 printf("step1 :依次输入A和B集合的元素个数(m,n):"); 82 scanf("%d,%d[^\n]", &m, &n); 83 printf("step2.1 :依次输入A中的元素到集合S: "); 84 for(j=1; j<=m; ++j){ 85 i = Malloc_SL(space); 86 printf(" 输入A中第%d/%d个元素:", j, m); 87 scanf("%s[^\n]", space[i].e.data); 88 //插入到表尾巴 89 space[r].cur = i; 90 r = i; 91 } 92 space[r].cur = 0; 93 Debug_Print(space, "step2.2 :创建集合A后的集合S值"); 94 95 printf("step3 :依次输入B中的元素,同时查找S表,如果已经存在则从S中删除之,否则加入到S! "); 96 ElemType b; 97 int p; 98 int k; 99 for(j=1; j<=n; ++j){ 100 memset(b.data, 0, sizeof(b.data)); 101 printf(" 输入B中第%d/%d个元素:", j, n); 102 scanf("%s[^\n]", b.data); 103 p = (*S); 104 k = space[p].cur; //k指向集合A中第一个结点 105 while(k!=space[r].cur && strncmp(space[k].e.data, b.data, sizeof(b.data))){ 106 //在当前表中查找 107 p = k; 108 k = space[k].cur; 109 } 110 if(k == space[r].cur){ 111 //当前表中不存在该元素, 插入在r所值结点后,且r的位置不变。 112 i = Malloc_SL(space); 113 space[i].e = b; 114 space[i].cur = space[r].cur; 115 space[r].cur = i; 116 snprintf(str, sizeof(str), "step3.1 :元素%s在S中不存在,插入之!",b.data); 117 Debug_Print(space, str); 118 }else{ 119 //该元素已在表中,则删除之 120 space[p].cur = space[k].cur; 121 Free_SL(space, k); 122 if(r == k){ 123 //如果删除的是r所指结点,则需修改尾指针。 124 r = p; 125 } 126 snprintf(str, sizeof(str), "step3.1 :元素%s在S中存在,删除之!",b.data); 127 Debug_Print(space, str); 128 } 129 } 130 } 131 132 int main(int argc, char *argv[]) 133 { 134 SLinkList space; 135 int s; 136 //求(A-B)U(B-A) 137 difference(space, &s); 138 return 0; 139 }
代码运行(静态单链表):
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 用静态链表算集合(A-B)U(B-A): step1 :依次输入A和B集合的元素个数(m,n):6,4 step2.1 :依次输入A中的元素到集合S: 输入A中第1/6个元素:c 输入A中第2/6个元素:b 输入A中第3/6个元素:e 输入A中第4/6个元素:g 输入A中第5/6个元素:f 输入A中第6/6个元素:d step2.2 :创建集合A后的集合S值 index 0 [data: ,cur:8 ] index 1 [data: ,cur:2 ] index 2 [data:c ,cur:3 ] index 3 [data:b ,cur:4 ] index 4 [data:e ,cur:5 ] index 5 [data:g ,cur:6 ] index 6 [data:f ,cur:7 ] index 7 [data:d ,cur:0 ] index 8 [data: ,cur:9 ] index 9 [data: ,cur:10] index 10 [data: ,cur:11] index 11 [data: ,cur:0 ] step3 :依次输入B中的元素,同时查找S表,如果已经存在则从S中删除之,否则加入到S! 输入B中第1/4个元素:a step3.1 :元素a在S中不存在,插入之! index 0 [data: ,cur:9 ] index 1 [data: ,cur:2 ] index 2 [data:c ,cur:3 ] index 3 [data:b ,cur:4 ] index 4 [data:e ,cur:5 ] index 5 [data:g ,cur:6 ] index 6 [data:f ,cur:7 ] index 7 [data:d ,cur:8 ] index 8 [data:a ,cur:0 ] index 9 [data: ,cur:10] index 10 [data: ,cur:11] index 11 [data: ,cur:0 ] 输入B中第2/4个元素:b step3.1 :元素b在S中存在,删除之! index 0 [data: ,cur:3 ] index 1 [data: ,cur:2 ] index 2 [data:c ,cur:4 ] index 3 [data:b ,cur:9 ] index 4 [data:e ,cur:5 ] index 5 [data:g ,cur:6 ] index 6 [data:f ,cur:7 ] index 7 [data:d ,cur:8 ] index 8 [data:a ,cur:0 ] index 9 [data: ,cur:10] index 10 [data: ,cur:11] index 11 [data: ,cur:0 ] 输入B中第3/4个元素:n step3.1 :元素n在S中不存在,插入之! index 0 [data: ,cur:9 ] index 1 [data: ,cur:2 ] index 2 [data:c ,cur:4 ] index 3 [data:n ,cur:8 ] index 4 [data:e ,cur:5 ] index 5 [data:g ,cur:6 ] index 6 [data:f ,cur:7 ] index 7 [data:d ,cur:3 ] index 8 [data:a ,cur:0 ] index 9 [data: ,cur:10] index 10 [data: ,cur:11] index 11 [data: ,cur:0 ] 输入B中第4/4个元素:f step3.1 :元素f在S中存在,删除之! index 0 [data: ,cur:6 ] index 1 [data: ,cur:2 ] index 2 [data:c ,cur:4 ] index 3 [data:n ,cur:8 ] index 4 [data:e ,cur:5 ] index 5 [data:g ,cur:7 ] index 6 [data:f ,cur:9 ] index 7 [data:d ,cur:3 ] index 8 [data:a ,cur:0 ] index 9 [data: ,cur:10] index 10 [data: ,cur:11] index 11 [data: ,cur:0 ] Process finished with exit code 0