/* 单链表: 优点: 1,解决了线性顺序表的长度固定的问题 2,删除、插入元素的时间复杂度为 O(1), 缺点: 读取元素时间复杂度为O(n) */ typedef int ElemType; typedef int Status; #define ERROR 0 #define OK 1 #define HEAD 0 struct Node { ElemType data; struct Node *Next; }; typedef Node* LinkList; /************************************************************************/ /* 创建一个有N个元素的单链表 */ /************************************************************************/ Status CreateLinkList(int N,LinkList *L) { /*万物的开始,神说要有光,于是便有了光 单链表说要有结点,于是便有了结点*/ *L=new Node; (*L)->data=0; /*头结点,尾结点都是我*/ (*L)->Next=NULL; #if HEAD /*头插法*/ LinkList p; for (int i=0;i<N;i++) { /*你要插入点东西吧*/ p=new Node; p->data=(i+1)*N; p->Next=NULL;/*注意了,这里一定要加NULL,不然到时候清空列表的时候p->Next不知道是什么了*/ /*算法关键在这里了,把新结点插到头结点和后面的结点之间。 所以就把头结点的后继,变成新结点的后继了。 此时头结点没后继了,不能断了香火呀,好吧,把新节点挂在头结点的后面,这样皆大欢喜*/ p->Next=(*L)->Next; (*L)->Next=p; } #else /*尾插法*/ /*一个是要插入的结点,一个是尾结点*/ LinkList p,r; /*尾巴*/ r=(*L); for (int i=0;i<N;i++) { /*新结点*/ p=new Node; p->data=(i+1)*N; p->Next=NULL;/*注意了,这里一定要加NULL,不然到时候清空列表的时候p->Next不知道是什么了*/ /*把新结点挂在当前链表的尾巴上*/ r->Next=p; /*长了根新尾巴*/ r=p; } #endif return OK; } /************************************************************************/ /* 获取第N个元素 */ /************************************************************************/ Status GetElem(int N,LinkList L,ElemType *e) { if (L==NULL) return ERROR; LinkList p=L; /*时间复杂度O(N)*/ int j=1; while(j<N &&p) { p=p->Next; ++j; } /*如果没找到point*/ if (!p ||j>N) return ERROR; (*e)=p->data; return OK; } /************************************************************************/ /* 插入第N个元素 */ /************************************************************************/ Status InsertElem(int N,LinkList *L,ElemType e) { if (L==NULL) return ERROR; LinkList p=(*L),q; /*下面这里是查找插入的位置的前一个结点。。。跟前面获取元素代码相同。 这个时间复杂度应该不要算在插入头上吧,如果要算的话,时间复杂度瞬间提升为O(n)。。。*/ int j=1; while (j<N-1 &&p) { p=p->Next; ++j; } /*如果没找到point*/ if (!p ||j>N-1) return ERROR; q=new Node; q->data=e; q->Next=p->Next; p->Next=q; return OK; } /************************************************************************/ /* 删除第N个元素 */ /************************************************************************/ Status DeleteElem(int N,LinkList *L,ElemType *e) { if (L==NULL) return ERROR; LinkList p=(*L),q; /*查找要删除的结点前驱位置*/ int j=1; while (j<N-1 &&p) { p=p->Next; ++j; } /*如果没找到point*/ if (!p ||j>N-1) return ERROR; q=p->Next; p->Next=q->Next; delete(q); return OK; } /************************************************************************/ /* 删除整个表 */ /************************************************************************/ Status ClearLinkList(LinkList *L) { if (L==NULL) return ERROR; LinkList p=(*L),q; while(1) { q=p->Next; p->Next=q->Next; delete(q); if (p->Next==NULL) { delete(p); break; } } return OK; }