首先指出我在学习过程中纠结的几个点:
1.初始化单链表的时候为什么要用二级指针?
反正那会也没学长指导,状态还差了点,但搜了很久后还是想明白了。
说白了你可以选择在定义头节点L的时候就初始化, 也可以定义了后用二级指针或者一级指针的引用传进函数InitList来初始化
2.为什么会需要头结点?
若头结点的指针域为空(NULL),表明链表是空表。头结点对于链表来说,不是必须的,在处理某些问题时,给链表添加头结点会使问题变得简单。
>>ADT:
typedef struct Node { DataType data; struct Node *next; }Node, *LinkList;
>>初始化:
void InitList(LinkList *L) { *L = (Node*)malloc(sizeof(Node)); (*L)->next = NULL; }
>>判断链表是否为空:
int Empty(Node *L) { if (L->next==NULL) return 1; else return 0; }
>>建立链表:
(1)头插法(逆序存储)
Node *CreatList1(DataType a[], int n) { Node *s = NULL; Node *L = (Node*)malloc(sizeof(Node)); L->next = NULL; for (int i = 0; i < n; i++) { s = (Node*)malloc(sizeof(Node)); s->data = a[i]; s->next = L->next; L->next = s; } return L; }
(2)尾插法
Node *CreatList2(DataType a[], int n) { Node *s = NULL, *rear = NULL; Node *L = (Node*)malloc(sizeof(Node)); rear = L; for (int i = 0; i < n; i++) { s = (Node*)malloc(sizeof(Node)); s->data = a[i]; rear->next = s; rear = s; } rear->next = NULL; return L; }
>>遍历链表:
void PrintList(Node *L) { Node *p = L->next; while (p!=NULL) { printf("%d", p->data); p = p->next; } }
>>链表长度:
int Length(Node *L) { Node *p = L->next; int cnt = 0; while (p!=NULL) { cnt++; p = p->next; } return cnt; }
>>查找节点
(1)按值查找
Node *Get(Node *L, DataType x) { Node *p = L->next; while (p&&p->data!=x) p = p->next; return p; }
(2)按位查找
Node *Locate(Node *L, int n) { if (n<=0) return NULL; Node *p = L; for (int i = 0; i < n; i++) p = p->next; return p; }
>>插入节点
int Insert(Node *L, int n, DataType x) { if (n<=0) return 0; Node *s = NULL, *p = L; int cnt = 0; while (p!=NULL&&cnt<n-1) { cnt++; p = p->next; } if (p==NULL) return 0; else { s = (Node*)malloc(sizeof(Node)); s->data = x; s->next = p->next; p->next = s; return 1; } }
>>删除节点
int Delete(Node *L, int n) { if (n<=0) return 0; Node *p = L; int cnt = 0; while (p!=NULL&&cnt<n-1) { cnt++; p = p->next; } if (p==NULL||p->next==NULL) return 0; else { Node *q = p->next;//单独设置一个指针指向被删除结点进行存储,以防丢失 p->next = q->next; free(q);//手动释放该结点,防止内存泄漏 return 1; } }
这些只是相对来说还不错的实现方法,当然也有别的写法,可以多看下别人的博客
总结:
线性表的链式存储相比于顺序存储,有两大优势:
1.链式存储的数据元素在物理结构没有限制,当内存空间中没有足够大的连续的内存空间供顺序表使用时,可能使用链表能解决问题。(链表每次申请的都是单个数据元素的存储空间,可以利用上一些内存碎片)
2.链表中结点之间采用指针进行链接,当对链表中的数据元素实行插入或者删除操作时,只需要改变指针的指向,无需像顺序表那样移动插入或删除位置的后续元素,简单快捷。
链表和顺序表相比,不足之处在于,当做遍历操作时,由于链表中结点的物理位置不相邻,使得计算机查找起来相比较顺序表,速度要慢。
感谢以下博客
https://www.cnblogs.com/ciyeer/p/9025871.html
https://blog.csdn.net/u012234115/article/details/39717215
https://www.cnblogs.com/longl/p/6414433.html