线性表—单链表的创建、查询、插入、删除、合并
1 #define ElemType int 2 #define OK 1 3 #define ERROR -1 4 #define Status int 5 6 typedef struct Lnode{ 7 ElemType data; 8 struct LNode *next; 9 }LNode, *LinkList; 10 //LinkList 相当于 LNode *
遇到的问题:
1.链表传入函数中要真正改变内容要对头节点的指针内容进行修改, 这里要区分开头节点和头节点的指针,
头节点的指针是LinkList 型的可以存储一个节点的地址,而头节点是一个实实在在的节点,它被头节点的指针索引。
2.上面定义的 * LinkList 其实和LNode * 是等价的 , 所以在开辟节点时候可以直接写: p = (LinkList)malloc(sizeof(LNode));
两种创建链表的方式:
1 Status CreatList_L1(LinkList *L, int n) 2 { 3 //尾插法创建链表 4 //要将创建的链表返回,所以要传入指针LinkList *L 5 LinkList p, q; 6 q = *L = (LinkList)malloc(sizeof(LNode)); 7 (*L)->next = NULL; 8 for(int i=0; i < n; i++) 9 { 10 p = (LinkList)malloc(sizeof(LNode)); 11 scanf("%d", &p->data); 12 q->next = p; 13 q = p; 14 } 15 p->next = NULL; 16 return OK; 17 }//CreatList_L1
1 Status CreatList_L2(LinkList *L, int n) 2 { 3 //头插法创建链表 4 (*L) = (LinkList)malloc(sizeof(LNode)); 5 (*L) ->next = NULL; //头插法一定加上这句 6 LinkList s; 7 for(int i=0; i < n; i++) 8 { 9 s = (LinkList)malloc(sizeof(LNode));//生成新节点 10 scanf("%d",&s->data); 11 s->next = (*L)->next; //将新开辟的节点查到头节点后面 12 (*L)->next = s; 13 } 14 return OK; 15 }//CreatList_L2
查询链表第i个位置的元素,并返回其值:
1 Status GetElem_L(LinkList L, int i, ElemType *e) 2 { 3 //L为带头节点的单链表的头指针 4 //但第i个元素存在时,其值赋给e并返回OK,否则返回ERROR 5 LinkList p = L; //初始化,p指向第1个节点 6 int j = 0; //计数器 7 while(p && j < i) //顺时针向后查找,直到p指向第i个元素或p为空 8 { 9 p = p->next; 10 j++; 11 } 12 if(!p || j > i) //第i个元素不存在 13 return ERROR; 14 *e = p->data; //取第i个元素 15 return OK; 16 }//GetElem_L
插入:
1 Status ListInsert_L(LinkList L, int i, ElemType e) 2 { 3 //在带头节点的单链线性表L第i个位置之前插入元素e 4 LinkList p = L, s; 5 int j = 0; 6 while(p && j < i-1) //寻找第i个节点,并令p指向其前驱 7 { 8 p = p->next; 9 j++; 10 } 11 if(!p || j > i - 1) //i小于1或着大于表长+1 12 return ERROR; 13 s = (LinkList)malloc(sizeof(LNode)); //生成新节点 14 s->data = e; //给新节点赋值 15 s ->next = p->next; //新节点指向第i个节点 16 p->next = s; //第i-1个节点指向新节点 17 return OK; 18 }//ListInsert_L
删除:
1 Status ListDelete_L(LinkList L, int i, ElemType *e) 2 { 3 //在带头节点的单链线性表L中,删除第i个元素,并由e返回其值 4 LinkList p = L, q; 5 int j = 0; 6 while(p && j < i-1) //寻找第i个元素,并令p指向其前驱 7 { 8 p = p->next; 9 j++; 10 } 11 if(!p || j > i-1) //删除位置不合理 12 return ERROR; 13 q = p->next; //q指向删除节点 14 *e = q->data; //e保存其值 15 p -> next = q->next; //移动指针跳过该节点 16 free(q); //释放空间 17 return OK; 18 }//ListDelete_L
合并:
1 void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) 2 { 3 //已知单链线性表La和Lb的元素按值非递减排列 4 //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列 5 LinkList pa = La->next; 6 LinkList pb = Lb->next; 7 (*Lc) = La; //用La的头节点作为Lc的头节点 8 LinkList pc = *Lc; 9 while(pa && pb) //与顺序表类似 10 { 11 if(pa->data <= pb->data) 12 { 13 pc->next = pa; 14 pc = pa; 15 pa = pa->next; 16 } 17 else 18 { 19 pc->next = pb; 20 pc = pb; 21 pb = pb->next; 22 } 23 } 24 pc->next = pa ? pa : pb; //插入剩余段 25 free(Lb); //释放Lb的头节点 26 }//MergeList_L
下面是完整代码,可以试一下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define ElemType int 5 #define OK 1 6 #define ERROR -1 7 #define Status int 8 9 typedef struct Lnode{ 10 ElemType data; 11 struct LNode *next; 12 }LNode, *LinkList; 13 //LinkList 相当于 LNode * 14 15 Status CreatList_L1(LinkList *L, int n) 16 { 17 //尾插法创建链表 18 //要将创建的链表返回,所以要传入指针LinkList *L 19 LinkList p, q; 20 q = *L = (LinkList)malloc(sizeof(LNode)); 21 (*L)->next = NULL; 22 for(int i=0; i < n; i++) 23 { 24 p = (LinkList)malloc(sizeof(LNode)); 25 scanf("%d", &p->data); 26 q->next = p; 27 q = p; 28 } 29 p->next = NULL; 30 return OK; 31 }//CreatList_L1 32 33 Status CreatList_L2(LinkList *L, int n) 34 { 35 //头插法创建链表 36 (*L) = (LinkList)malloc(sizeof(LNode)); 37 (*L) ->next = NULL; //头插法一定加上这句 38 LinkList s; 39 for(int i=0; i < n; i++) 40 { 41 s = (LinkList)malloc(sizeof(LNode));//生成新节点 42 scanf("%d",&s->data); 43 s->next = (*L)->next; //将新开辟的节点查到头节点后面 44 (*L)->next = s; 45 } 46 return OK; 47 }//CreatList_L2 48 49 Status GetElem_L(LinkList L, int i, ElemType *e) 50 { 51 //L为带头节点的单链表的头指针 52 //但第i个元素存在时,其值赋给e并返回OK,否则返回ERROR 53 LinkList p = L; //初始化,p指向第1个节点 54 int j = 0; //计数器 55 while(p && j < i) //顺时针向后查找,直到p指向第i个元素或p为空 56 { 57 p = p->next; 58 j++; 59 } 60 if(!p || j > i) //第i个元素不存在 61 return ERROR; 62 *e = p->data; //取第i个元素 63 return OK; 64 }//GetElem_L 65 66 Status ListInsert_L(LinkList L, int i, ElemType e) 67 { 68 //在带头节点的单链线性表L第i个位置之前插入元素e 69 LinkList p = L, s; 70 int j = 0; 71 while(p && j < i-1) //寻找第i个节点,并令p指向其前驱 72 { 73 p = p->next; 74 j++; 75 } 76 if(!p || j > i - 1) //i小于1或着大于表长+1 77 return ERROR; 78 s = (LinkList)malloc(sizeof(LNode)); //生成新节点 79 s->data = e; //给新节点赋值 80 s ->next = p->next; //新节点指向第i个节点 81 p->next = s; //第i-1个节点指向新节点 82 return OK; 83 }//ListInsert_L 84 85 Status ListDelete_L(LinkList L, int i, ElemType *e) 86 { 87 //在带头节点的单链线性表L中,删除第i个元素,并由e返回其值 88 LinkList p = L, q; 89 int j = 0; 90 while(p && j < i-1) //寻找第i个元素,并令p指向其前驱 91 { 92 p = p->next; 93 j++; 94 } 95 if(!p || j > i-1) //删除位置不合理 96 return ERROR; 97 q = p->next; //q指向删除节点 98 *e = q->data; //e保存其值 99 p -> next = q->next; //移动指针跳过该节点 100 free(q); //释放空间 101 return OK; 102 }//ListDelete_L 103 104 void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) 105 { 106 //已知单链线性表La和Lb的元素按值非递减排列 107 //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列 108 LinkList pa = La->next; 109 LinkList pb = Lb->next; 110 (*Lc) = La; //用La的头节点作为Lc的头节点 111 LinkList pc = *Lc; 112 while(pa && pb) //与顺序表类似 113 { 114 if(pa->data <= pb->data) 115 { 116 pc->next = pa; 117 pc = pa; 118 pa = pa->next; 119 } 120 else 121 { 122 pc->next = pb; 123 pc = pb; 124 pb = pb->next; 125 } 126 } 127 pc->next = pa ? pa : pb; //插入剩余段 128 free(Lb); //释放Lb的头节点 129 }//MergeList_L 130 131 int main() 132 { 133 int n; 134 LinkList L, p, s; 135 scanf("%d",&n); 136 CreatList_L1(&L, n); 137 printf("\n~~~\n"); 138 p = L->next; 139 while( p != NULL){ 140 printf("%d ",p->data); 141 p = p->next; 142 } 143 printf("\n"); 144 145 int i, e; 146 printf("查询位置: "); 147 scanf("%d",&i); 148 GetElem_L(L, i, &e); 149 printf("e == %d\n",e); 150 151 printf("插入位置、元素:"); 152 scanf("%d%d",&i,&e); 153 ListInsert_L(L, i, e); 154 p = L->next; 155 while(p){ 156 printf("%d ",p->data); 157 p = p->next; 158 } 159 printf("\n"); 160 161 printf("删除位置:"); 162 scanf("%d",&i); 163 ListDelete_L(L, i, &e); 164 printf("e == %d\n",e); 165 166 int a[ ]= {3, 5, 8, 11}; 167 int b[ ]= {2, 6, 8, 9, 11, 15, 20}; 168 LinkList La, Lb; 169 La = (LinkList)malloc(sizeof(LNode)); 170 Lb = (LinkList)malloc(sizeof(LNode)); 171 La->next = Lb->next = NULL; 172 p = La; 173 for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++) 174 { 175 s = (LinkList)malloc(sizeof(LNode)); 176 s->data = a[i]; 177 p->next = s; 178 p = s; 179 } 180 p->next = NULL; 181 182 p = Lb; 183 for(int i = 0; i<sizeof(b)/sizeof(b[0]); i++) 184 { 185 s = (LinkList)malloc(sizeof(LNode)); 186 s->data = b[i]; 187 p->next = s; 188 p = s; 189 } 190 p->next = NULL; 191 192 printf("La = "); 193 p = La->next; 194 while(p) 195 { 196 printf("%d ",p->data); 197 p = p->next; 198 } 199 printf("\n"); 200 p = La->next; 201 202 printf("Lb = "); 203 p = Lb->next; 204 while(p) 205 { 206 printf("%d ",p->data); 207 p = p->next; 208 } 209 printf("\n"); 210 211 LinkList Lc; 212 MergeList_L(La, Lb, &Lc); 213 214 printf("MergeList = "); 215 p = Lc->next; 216 while(p) 217 { 218 printf("%d ", p->data); 219 p = p->next; 220 } 221 printf("\n"); 222 223 224 return 0; 225 }