一.特点:
(1)有一个head指针变量,存放头结点的地址,称为头指针。
(2)头结点的指针域head—>,存放第一个有效节点的地址。
(3)每个节点都包含一个数据域和指针域,数据域存放此节点的数据,指针域存放下一个节点的地址。最后一个节点的指针域为NULL,防止乱指。
(4)链表中各节点的顺序关系由指针域next确定,随机分配空间,不需要占用连续的内存空间。
二. 增删改查
首先建立一个结构体:
typedef struct node
{
int a;
char b;
struct node* next; //定义一个指向本结构体类型的指针类型
}Node,*LinkList; //Node是结构体类型,是struct node的别名,
LinkList是结构体指针类型,LinkList head相当于 Node* head,也相当于struct node* head
1. 增
(1)尾插法
void Creat_Rear(LinkList head)
{
LinkList head1 = NULL, p1 = NULL, p2 = NULL; //在vs中必须初始化为空,否则乱指
p2 = head1;
int a;
char b[20];
while (1)
{
scanf("%d %s", &a, b);
if (a == 0)
break;
p1 = (Node*)malloc(sizeof(Node)); //首先申请空间
strcpy(p1->b, b); //传入字符串b的数据
p1->a = a; //传入整形数据a
p2->next = p1;
p2 = p1;
}
p2->next = NULL; //最后一个结点的指针域为空
}
(2)头插法
缺点:数据读入顺序和链表中结点顺序相反
void Creat_head(LinkList head)
{
LinkList head2 = NULL, p1 = NULL, p2 = NULL;
p2 = head2;
int a;
char b[20];
while (1)
{
scanf("%d %s", &a, b);
if (a == 0)
break;
p1 = (Node*)malloc(sizeof(Node));
strcpy(p1->b, b);
p1->next = head->next; //将新建立结点指向头的下一个结点
head->next = p1; //head的指针域指向新建立的结点
}
}
(3)插入结点到第几个结点的位置
LinkList Insert(LinkList head, int i)
{
Node* p , * s;
s = (Node*)malloc(sizeof(Node));
int a;
char b[20];
scanf("%s", p->b);
scanf("%d",&p->a);
if (i == 1)
{
s->next = head;
head = s;
}
else
{
int j = 1;
p = head;
while (j < i - 1 &&p) //遍历到插入位置的前一个结点
{
p = p->next;
j++;
}
if (p)
{
s->next = p->next;
p->next = s;
}
}
return head;
}
2. 删
LinkList Delete(LinkList head, int n)
{
Node* p = head, * q;
int n;
scanf("%d", &n);
if (head == NULL)
{
printf("the n is error!");
return;
}
if (n == 1) //删除第一个结点的特殊情况
{
q = head;
head = head->next;
free(q);
}
else
{
int j = 1;
while (j < n - 1 && p)
{
p = p->next;
j++;
}
if (p == NULL || p->next == NULL) //p为需删除结点的前一个,
所以如果删除的前一个或者删除的结点为空,则错误
{
printf("the n is error!");
}
else
{
q = p->next;
p->next = q->next;
free(q);
}
}
return head;
}
3. 查
LinkList Search(LinkList head)
{
int x;
LinkList p;
scanf("%d", &x);
while(p != NULL && p->a != NULL)
{
p = p->next; //没找到查询的结点继续向下找
}
if (p == NULL)
{
printf("没有找到该点!");
return NULL;
}
return head;
}
4. 改
void Modify(LinkList head)
{
LinkList p = Search(head); //调用“查”的程序
if (p == NULL)
{
return;
}
int val;
scanf("%d", &val);
p->a = val; //修改数据
return;
}
5. 逆置
void Reverse(LinkList head)
{
Node* p, * q;
p = head->next;
while (p)
{
q = p->next;
p->next = head->next;
head->next = p;
p = q;
}
}