回顾:动态分配和撤销内存
#include <stdio.h>
#include <malloc.h>
struct Student
{
int 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\n", p->num, p->score);
free(p);
return 0;
}
遍历链表
void traverse(Node *h)
{
Node *p;
p = h; /*p指向头结点*/
while(p!=NULL)
{
printf("%-5d", p->data); /*“访问”结点,此处用最简单的操作:读取输出*/
p = p->next; /*p指向下一个结点,继续处理*/
}
printf("\n");
return;
}
创建一个链表
#include <stdio.h>
#include <malloc.h>
typedef struct NODE
{
int data;
struct NODE *next;
} Node;
Node *createLinkList(int n);
void traverse(Node *h);
int main( )
{
Node *head;
head = createLinkList(5);
traverse(head);
return 0;
}
Node *createLinkList(int n)
{
Node *h=NULL, *p, *last; /*h指向头结点,p指向新增结点,last指向尾结点*/
int d; /*用于输入要插入的元素的值*/
int i;
for(i=0; i<n; i++)
{
scanf("%d", &d);
p = (Node *)malloc(sizeof(Node)); /*p指向新增的结点*/
p->data = d; /*为数据域赋值*/
p->next = NULL; /*指针域为空*/
if (h==NULL) /*如果h==NULL为真,说明p为第一个结点,由h指向该结点*/
h = p;
else /*否则,原最后一个结点指向新增的结点,新结点加在链表尾*/
last->next = p;
last= p; /*last保持指向最后一个结点的角色*/
}
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;
}
插入结点应用——建立有序链表
#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;
}
删结点应用——在有序表中删除
#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;
}