链表 :
结点模型
数据域 | 指针域
数据域存放数据,指针域存放下一个节点的地址;
头结点:
不存放数据
头指针:
存放头结点地址的指针
链表初始化:
struct node
{
int data;
struct node *next;
};
typedef struct node Node;
头文件中:
#ifndef _LINKLIST_H
#define _LINKLIST_H
#define SUCCESS 10001
#define FAILURE 10002
#define TRUE 10000
#define FALSE 10003
typedef int ElemType;
struct node
{
ElemType data;
struct node *next;
};
typedef struct node Node;
int Linkinnit(Node **l);
int Linkinsert(Node *l, int n, ElemType e);
int Linktraver(Node *l, void (*p)(ElemType));
int Linkempty(Node *l);
int Linkget(Node *l, int p, ElemType *e);
int Linkgget(Node *l, ElemType e, int (*p)(ElemType, ElemType));
int Linkdelete(Node *l, int p, ElemType *e);
int Linkclear(Node *l);
int Linkdestory(Node **l);
int Linkreverse(Node *l);
#endif
初始化子函数:
int Linkinit(Node **l) //传入的实参是指针的地址,所以形参需要定义二级指针
{
*l = (Node *)malloc(sizeof(Node) * 1);
if(l == NULL)
{
return FAILURE;
}
(*l)->next = NULL; //初始化头结点
return SUCCESS;
}
初始化主函数;
Node *list = NULL;
int ret, i;
srand(time(0));
ret = Linkinit(&list); //为了修改空指针list中的值,需要将list的地址作为实参传出
if(ret == SUCCESS)
{
printf("INIT SUCCESS\n");
}
else
{
printf("INIT FAILURE\n");
}
单链表插入操作:
子函数:
int Linkinsert(Node *l, int n, ElemType e)
{
Node *p = l;
int k = 1;
if(l == NULL) //入参判断,良好的编码习惯
{
return FAILURE;
}
while(k < n && p != NULL) //这段代码是寻找到需要插入的节点前一个位置
{ //由于单链表是单向的,一旦遍历错过这个节点只能从头结点
p = p->next; //重新遍历,循环的条件是防止插入的位置太大,以至于打过
k++; //链表的长度
}
if(k > n || p == NULL)
{
return FAILURE;
}
Node *q = (Node *)malloc(sizeof(Node) * 1); //新建一个节点,就是即将插入链表中的节点
if(NULL == q)
{
return FAILURE;
}
q->data = e; // 这是单链表插入的核心代码
q->next = p->next;
p->next = q;
return SUCCESS;
主函数:
for(i = 0; i < 10; i++)
{
ret = Linkinsert(list, i + 1, rand() % 20 );
if(ret == SUCCESS)
{
printf("INSERT SUCCESS!\n");
}
else
{
printf("INSERT FAILURE!\n");
}
}