建立结构体
和带头结点但单链表一样,按需建立即可。我以建立一个储存学生信息的链表举例。
typedef struct node
{
char name[20];
int number;
struct node *next;
}Node,*LinkList;
单链表的建立
因为不带头结点,无需初始化,最后返回head
尾插法
如果是第一个结点,则需让head指向这个结点,再利用另一指针r保存head,并用r进行之后的节点插入。除第一个结点外其他结点的插入与带头结点的单链表一致。
LinkList CreatByRear()
{
LinkList head = NULL;
Node *r=NULL, *s;
char name[20];
int number;
printf("请输入学生的姓名和学号:\n");
while (1)
{
scanf("%s", name);
scanf("%d", &number);
if (number == 0)
break;
s = (Node*)malloc(sizeof(Node));
strcpy(s->name, name);
s->number = number;
s->next = NULL;
if (head == NULL)
{
head = s;
r = head;
}
else
{
r->next = s;
r = s;
}
}
return head;
}
头插法
并不需要对第一个结点做特殊处理,可以当作是一直在第一个结点前插入新结点。
LinkList CreatByHead()
{
LinkList head = NULL;
Node *s;
char name[20];
int number;
printf("请输入\n");
while (1)
{
scanf("%s", name);
scanf("%d", &number);
if (number == 0)
break;
s = (Node*)malloc(sizeof(Node));
strcpy(s->name, name);
s->number = number;
s->next = head;
head = s;
}
return head;
}
查询
与带头结点的单链表基本一致,知识循环初始点不同。
LinkList Find(LinkList head, int i)
{
Node *p = head;
int j = 1;
while (p&&j < i)
{
p = p->next;
j++;
}
return p;
}
插入
如插入在第一格结点前,则需改变head的值,在第一个结点之后,则无需改变head的值,先找到插入点的地址正常差入就好。
LinkList Insert(LinkList head, int i)
{
Node *p, *s;
if (i == 1)
{
printf("请输入待添加的学生的姓名和学号:\n");
s = (Node*)malloc(sizeof(Node));
scanf("%s%d", s->name, &s->number);
s->next = head;
head = s;
}
else
{
p = Find(head, i - 1);
if (p)
{
printf("请输入待添加的学生的姓名和学号:\n");
s = (Node*)malloc(sizeof(Node));
scanf("%s%d", s->name, &s->number);
s->next = p->next;
p->next = s;
}
else
printf("EORROR\n");
}
return head;
}
删除
如插入在第一格结点前,则需改变head的值,在第一个结点之后,则无需改变head的值,先找到待删除结点的地址正常删除就好。
LinkList Delete(LinkList head, int pos)
{
Node *p = head, *q;
printf("删除第%d个学生\n", pos);
if (pos == 1)
{
q = head;
head = head->next;
free(q);
}
else
{
p = Find(head, pos - 1);
if (p == NULL || p->next == NULL)
{
printf("EORROR\n");
}
else
{
q = p->next;
p->next = q->next;
free(q);
}
}
return head;
}