线性表的链式结构,与之前说过的线性表的顺序结构差不多,区别在于存储结构和方式的不一样。
在链式中,来一个数据就去寻找一个空间存储一个结点有多少数据占多大的地方,是动态的存储方式。另外顺序表如果存储1MB就只占1MB存储空间,但是链式表不一样,它会有额外的空间去存储对应结点的指针。
这样一分析结构就出来了,链式结构为两部分:1.结点域。2.指针域。实现方法用动态存储。
1 #include "stdio.h" 2 #include "stdlib.h" 3 4 typedef int ElemType; 5 typedef int Status; 6 #define ERROR 0 7 #define OK 1 8 9 typedef struct LNode 10 { 11 ElemType data; //数据域 12 struct LNode *next; //指针域 13 }LNode, *LinkList; 14 15 //构建一个空的线性表L 16 Status InitList(LinkList &L) 17 { 18 L = (LinkList)malloc(sizeof (LNode)); //产生头结点,并使L指向头结点 19 if(!L) 20 return ERROR; 21 L->next = NULL; 22 return OK; 23 }//InitList 24 25 //销毁线性表L 26 Status DestroyList(LinkList &L) 27 { 28 LinkList p; 29 while(L) //循环释放结点 30 { 31 p = L->next; 32 free(L); 33 L = p; 34 } 35 return OK; 36 }//DestroyList 37 38 //重置线性表L为空表 39 Status ClearList(LinkList L) 40 { 41 LinkList p = L->next, q; 42 while (p) //循环释放结点 43 { 44 q = p->next; 45 free(p); 46 p = q; 47 } 48 L->next = NULL; //头结点指针域为空s 49 return OK; 50 }//ClearLIst 51 52 //判断线性表是否为空表 53 Status ListEmpty(LinkList L) 54 { 55 if(L->next) 56 return true; //非空返回OK 57 else 58 return false; //空表返回ERROR 59 }//ListEmpty 60 61 //返回线性表L中的个数 62 int ListLength(LinkList L) 63 { 64 int i = 0; 65 LinkList p = L->next; //p指向第一个结点 66 while(p) //循环到表尾 67 { 68 p = p->next; 69 ++i; 70 } 71 return i; 72 }//ListLength 73 74 //当第i个元素存的时,赋值给e并返回OK,否则返回ERROR 75 Status GetElem(LinkList L, int i, ElemType &e) 76 { 77 LinkList p = L->next; //p指向第一个结点 78 int j = 1; 79 while(p && j < i) //顺指针向后查找,直到p指向第i个元素或p为空 80 { 81 p = p->next; 82 ++j; 83 } 84 if(!p || (j > i)) //判断位置是否合法 85 return ERROR; 86 e = p->data; //取第i个元素 87 return OK; 88 }//GetElem 89 90 //返回L中第一个与e满足compare()的数据元素的位序,诺不存在则返回ERROR 91 //compare()是数据元素判定函数 92 Status LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType,ElemType)) 93 { 94 int j = 0; 95 LinkList p = L->next; 96 while(p) 97 { 98 ++j; 99 if(compare(p->data,e)) 100 return j; 101 p = p->next; 102 } 103 return ERROR; 104 }//LocateElem 105 106 //若cur_e是L的数据元素,且不是第一个。则用pre_e返回他的前驱, 107 //否则操作失败,pre_e无定义 108 Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e) 109 { 110 LinkList p = L->next, q; //p指向第一个结点 111 while(p->next) //p指的结点有后驱 112 { 113 q = p->next; //q为p的后驱 114 if(q->data == cur_e) 115 { 116 pre_e = p->data; //获取前驱数据 117 return OK; 118 } 119 p = q; 120 } 121 return ERROR; 122 }//PriorElem 123 124 //若cur_e是L的数据元素,且不是最后一个。则用next_e返回他的后驱, 125 //否则操作失败,next_e无定义 126 Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e) 127 { 128 LinkList p = L->next; 129 while(p->next) 130 { 131 if(p->data == cur_e) 132 { 133 next_e = p->next->data; //获取后驱数据 134 return OK; 135 } 136 p = p->next; 137 } 138 return ERROR; 139 }//NextElem 140 141 //在第i个位置之前插入元素e 142 Status ListInsert(LinkList &L, int i, ElemType e) 143 { 144 LinkList p = L; //p指向第一个结点 145 int j = 0; 146 while (p && j < i-1) //寻找第i-1个结点 147 { 148 p = p->next; 149 ++j; 150 } 151 if(!p || j > i-1) //判断位置是否合法 152 return ERROR; 153 LinkList s = (LinkList)malloc(sizeof (LNode)); //创建新结点 154 //插入L中 155 s->data = e; 156 s->next = p->next; 157 p->next = s; 158 return OK; 159 }//ListInsert 160 161 //删除第i个结点,并用e返回其值 162 Status ListDelete(LinkList &L, int i, ElemType &e) 163 { 164 LinkList p = L; 165 int j = 0; 166 while (p->next && j < i-1) //寻找i-1结点 167 { 168 p = p->next; 169 ++j; 170 } 171 if(!(p->next) || j > i-1) //位置不合理 172 return ERROR; 173 //删除结点并释放空间 174 LinkList q = p->next; 175 p->next = q->next; 176 e = q->data; 177 free(q); 178 return OK; 179 }//ListDelete 180 181 //依次对L的每个元素调用函数Visit(),一旦失败,则操作失败 182 Status ListTraverse(LinkList L, void (*Visit)(ElemType)) 183 { 184 LinkList p = L->next; 185 while(p) 186 { 187 Visit(p->data); 188 p = p->next; 189 } 190 printf("\n"); 191 return OK; 192 }//ListTraverse 193 194 //ListTraverse()调用的函数 195 void Visit(ElemType c) 196 { 197 printf("%d ", c); 198 }//Visit
线性表的链式结构的基本操作函数的实现。
参考《数据结构(C语言版)》
时间: 2024-10-07 19:25:09