一,链表的认识
链表初始化的作用 :
生成链表头指针,以便后续函数的调用操作,在没有任何输入的情况下,我们首先定义一个头指针来保存即将创建的链表
链表是一种常见的重要的数据的存储结构
特点:
1结点地址不是连续的
2用上一个节点中的地址才能找到下一结点
链表的初始化:
用指针的结构体来实现
struct Node
{
char data; //用来存储数据
struct Node *next; //用来保存地址,寻找结点
};
struct Node *head //定义一个链表头指针
二, 建立并输出一个如图所示的简单的链表
#include <stdio.h>
struct student
{
int num;
float score;
struct student *next;
};
int main()
{
struct student a, b, c, *head, *p;//a b c 为三个结点 *head为头指针
//将各个结点赋值
//将结点连起来
//将链表输出
return 0;
}
1,将各结点赋值
a.num = ?;
a.score = ?;
b.num = ?;
b.score = ?;
c.num = ?;
c.score = ?;
2,将各个结点连起来
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
3,输出个链表
p = head;
do
{
printf("%d %.1f\n",&p->score,&p->num);
p=p->next;
}while(P!=NULL);
三,链表中结点的插入和删除
1,动态分配和创建内存
#include <stdio.h>
struct student
{
char num;
float score;
struct student *next;
};
int main()
{
struct student *p;
p = malloc(sizeof(struct student));//动态分配内存
p->num = 31001;
p->score = 89.5;
printf("%d %.1f",&p->num,&p->score);
free(p);//撤销内存
return 0;
}
2,遍历链表(访问链表内的值并输出)
typedef struct NODE
{
int data;
struct NODE *next;
}Node;
void traverse(Node *h)
{
Node *p;
p=h; //P指向头节点
while(P->next = NULL) //遍历标志
{
printf("%d",p->data); //访问节点
p=p->next; //指向下一结点
}
printf("\n");
return 0;
}
3,创建一个链表
P是媒介
传递头指针给h,传递结点给last
last 是p新建的结点(新结点或下一个结点)
#include <stdio.h>
#include <malloc.h>
void traverse(Node *h)
Node *creatLinkList(int n)
typedef struct NODE
{
int data;
struct NODE *next;
}Node;
Node *creatLinkList(int n)
{
Node *h = NUll,*p,*last;
int i;
int d;
for(i=0;i<n;i++)
{
scanf("%d",&d);//用于给第一个头指针赋值
p=(Node*)malloc(sizeof(Node));
p->data =d;
p->next = NULL;
if(h == NULL)
{
h=p;
}
else
last->next = p;
last = p;
}
return h;//保存头结点
}
int main()
{
Node *head;
head = creatLinkList(5);//实参为5传递给形参n 让其循环5次 建立五个结点
traverse(head);
return 0;
}
void traverse(Node *h)//此h是形参 实参为head 并非creatLinkList中h
{
Node *p;
p = h;
while(p!=NULL)
{
printf("%-5d",p->data);
p=p-next;
}
printf(""\n);
return;
}
4,在链表中插入一个结点
目的:
过程:
注意顺序不能发生改变
插入结点的应用-建立有序列表
例:将如图结点按顺序排列
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
int data;
struct NODE *next;
} Node;
Node *insertNode(Node *h, int b);
void traverse(Node *h);
int main( )
{
int b[]= {67, 25, 78, 99, 87},i;
Node *head=NULL;
for(i=0; i<5; i++)
head=insertNode(head, b[i]);
traverse(head);
return 0;
}
Node *insertNode(Node *h, int b)
{
Node *q1=h,*q2,*p;
p=(Node*)malloc(sizeof(Node)); /*生成新结点*/
p->data=b;
if(h==NULL) /*当前链表为空,p作为首结点*/
{
h=p; /*头结点就是p,将p赋值给h*/
p->next=NULL; /*p的指针域赋值为空,表示尚无下一个结点*/
}
else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
{
h=p; /*将头结点h赋值为p*/
p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
}
else /*在中间找到插入p的位置,将其插入*/
{
/*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
while((q1!=NULL&&p->data>=q1->data))
{
q2=q1; /*q2记录q1的值*/
q1=q1->next; /*q1继续向后试探,直到a1*/
}
/*将新结点p插在q2后*/
p->next=q2->next; /*p的下一个结点为当前q2的下一结点,即p1*/
q2->next=p; /*q2的下一个结点y变为p,不再是q1*/
}
return h;
}
void traverse(Node *h)
{
Node *p;
p = h; /*p指向头结点*/
while(p!=NULL)
{
printf("%-5d", p->data); /*“访问”结点,此处用最简单的操作:读取输出*/
p = p->next; /*p指向下一个结点,继续处理*/
}
printf("\n");
return;
}
5,在链表中删除结点
目的:
过程:
删除结点应用-在有序表中删除
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
int data;
struct NODE *next;
} Node;
Node *insertNode(Node *h, int b);
Node *deleteNode(Node *h, int b);
void traverse(Node *h);
int main( )
{
int b[]= {67, 25, 78, 99, 87},i;
Node *head=NULL;
for(i=0; i<5; i++)
head=insertNode(head, b[i]);
traverse(head);
head=deleteNode(head, 43);
traverse(head);
head=deleteNode(head, 78);
traverse(head);
return 0;
}
Node *insertNode(Node *h, int b)
{
Node *q1=h,*q2,*p;
p=(Node*)malloc(sizeof(Node)); /*生成新结点*/
p->data=b;
if(h==NULL) /*当前链表为空,p作为首结点*/
{
h=p; /*头结点就是p,将p赋值给h*/
p->next=NULL; /*p的指针域赋值为空,表示尚无下一个结点*/
}
else if(p->data<h->data) /*要插入的元素值小于首结点元素,插入结点作为首结点*/
{
h=p; /*将头结点h赋值为p*/
p->next=q1; /*p的下一个结点是原先的首结点(见q1的初始化,其值为h)*/
}
else /*在中间找到插入p的位置,将其插入*/
{
/*先找到合适的位置,q1的初值是h,即从头结点开始考察*/
while((q1!=NULL&&p->data>=q1->data))
{
q2=q1; /*q2记录q1的值*/
q1=q1->next; /*q1继续向后试探,直到a1*/
}
/*将新结点p插在q2后*/
p->next=q2->next; /*p的下一个结点为当前q2的下一结点,即p1*/
q2->next=p; /*q2的下一个结点y变为p,不再是q1*/
}
return h;
}
Node *deleteNode(Node *h, int b)
{
Node *p, *q;
p=h; /*p首先指向头结点*/
if(h==NULL) /*链表为空时不能删除*/
printf("List is null, delete fail.\n");
else
{
/*首先找到要删除的结点*/
while(b!=p->data&&p->next!=NULL)
{
q=p; /*q记录p的值*/
p=p->next; /*p接着指向下一个结点,q一直保持是p的上一个结点*/
}
if(b==p->data) /*要删除的结点p在链表中存在*/
{
if(p==h) /*要删除的结点就是头结点时,令h指向p的下一个结点即可*/
h = p->next;
else /*否则,删除q的下一个结点p*/
q->next = p->next;
free(p); /*释放p结点*/
}
else
printf("%d not found, delete fail.\n", b);
}
return h;
}
void traverse(Node *h)
{
Node *p;
p = h; /*p指向头结点*/
while(p!=NULL)
{
printf("%-5d", p->data); /*“访问”结点,此处用最简单的操作:读取输出*/
p = p->next; /*p指向下一个结点,继续处理*/
}
printf("\n");
return;
}