链表是一种常见的重要数据结构,它可以动态地进行存储分配,根据需要开辟内存单元,还可以方便地实现数据的增加和删除。链表中的每个元素都由两部分组成:数据域和指针域。
其中,数据域用来存储数据元素的信息,指针域用来存储该元素的直接后继元素的位置。其整体结构就是用指针相链接起来的线性表,如下图所示:
下面通过实例说明单链表使用方法,在该实例中可实现在任意位置增加或删除结点。
#include "stdafx.h"
#include <stdlib.h>
/*定义链表结点*/
struct student
{
int num;
float score;
struct student *nest; /*C语言语法:结构的成员不能是结构自身类型,
但结构的成员可以是结构自身的指针类型*/
};
struct student *head=NULL,*s1,*s2; /*定义结构体变量,但是此时这些变量中的
指针成员指向的地址并不确定,所以还不能用*/
/*函数声明*/
void init_node(void);
void show_node(void);
void print_info(void);
struct student * insert_node(void);
struct student * delete_node(void);
/*主函数*/
int main(int argc, char* argv[])
{
int a;
init_node();
print_info();
while(1)
{
scanf("%d",&a);
if(1==a){
head=insert_node();
}
if(2==a){
head=delete_node();
}
if(3==a){
show_node();
}
}
return (0);
}
/*提示信息打印函数*/
void print_info(void)
{
printf("*************************\n");
printf("input 1:insert link node\n");
printf("input 2:delete link node\n");
printf("input 3:show link node\n");
printf("*************************\n");
}
/*初始结点创建函数*/
void init_node(void)
{
head=s1=(struct student *) malloc(sizeof(struct student)); //head指针指向第一个链表节点
s2=(struct student *) malloc(sizeof(struct student));
head->nest=s1; //头结点next指向p1结点
/*p1结点成员赋值*/
s1->num=1001;
s1->score=89;
s1->nest=s2;
s2->num=1005;
s2->score=95;
s2->nest=NULL;
}
/*遍历链表结点打印函数*/
void show_node(void)
{
struct student *p;
p=head;
for(p=head;p!=NULL;p=p->nest)
{
printf("%d %.1f\n",p->num,p->score);
}
}
/*插入结点函数*/
struct student * insert_node(void)
{
struct student *p1,*p0; //临时结点指针
struct student *p3 = (struct student *) malloc(sizeof(struct student)); //定义结点变量,并分配空间
printf("insert node: ");
scanf("%d %f",&(p3->num),&(p3->score)); //输入数据保存在对应地址中
p1=head; //p1指向头结点
/*p1从头结点开始,将其num域与输入的数值比较,
小于则指向下一个结点,直到大于输入值才退出*/
while((p1->nest!=NULL) &&( p1->num < p3->num))
{
p2=p1;
p1=p1->nest;
}
if(p1->num > p3->num) //找到大于输入值的结点
{
if(p1==head) //结点为头结点时
{
head=p3;
p3->nest=p1;
}else //结点为中间结点
{
p2->nest=p3;
p3->nest=p1;
}
}else //结点为尾结点
{
p1->nest=p3;
p3->nest=NULL;
}
return head; //头指针有可能被改变,因此返回
}
/*删除结点函数*/
struct student * delete_node(void)
{
int num,i;
struct student *p1,*p2;
printf("delete node: ");
scanf("%d",&num);
p1=head;
/*从头指针开始,比较结点num域值域输入值,
不相等则保存当前结点,并指向下个结点*/
while(p1!=NULL && p1->num!=num)
{
p2=p1;
p1=p1->nest;
}
if(p1->num == num)
{
if(p1==head) //删除头结点
head=p1->nest;
else //删除中间结点或尾结点
p2->nest=p1->nest;
free(p1); //一定记得释放内存空间,不然会造成内存泄漏
}
return head; //头指针同样有可能被改变,因此返回
}
2、写一个函数将一个链表逆序
Node * ReverseList(Node *head) //链表逆序, 不带头结点
{
if ( head == NULL || head->next == NULL ) //not empty
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
2. 写一个函数将两个有序链表(从小到大)合并
Node * MergeList(Node *first, Node *second)
{
Node *third=NULL;
Node *p=NULL;
Node *tmp=NULL;
if(first==NULL) return second;
if(second==NULL) return first;
while(first && second)
{
if(first->key <= second->key)
{
tmp=first;
first=first->next;
}
else
{
tmp=second;
second=second->next;
}
if(third==NULL)
{
third=p=tmp;
}
else
{
p->next=tmp;
p=tmp;
}
}
p->next=first?first:second;
return third;
}
2、双链表
// linking.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int a[5] = {1,2,3,4,5};
typedef struct _node
{
void *data;
struct _node *pier;
struct _node *next;
}NODE;
typedef struct
{
NODE *head;
NODE *last;
int length;
}LIST;
LIST * InitList()
{
LIST *l = (LIST *)malloc(sizeof(LIST));
if(NULL == l) exit (0);
l->head = (NODE *)malloc(sizeof(NODE));
if(NULL == l->head) exit (0);
memset(l->head,0,sizeof(NODE));
l->last = (NODE *)malloc(sizeof(NODE));
if(NULL == l->last) exit (0);
memset(l->last,0,sizeof(NODE));
l->head->next = l->last;
l->last->pier = l->head;
l->length = 0;
return l;
}
int InsertNode(LIST *l,void *data,int size)
{
NODE *n = NULL;
if(NULL == l || NULL == data || size<=0)
return 0;
n = (NODE *)malloc(sizeof(NODE));
if(NULL == n) return 0;
n->data = malloc(sizeof(size));
if(n->data == NULL)
{
free (n);
return 0;
}
memcpy(n->data,data,size);
n->next = l->last;
n->pier = l->last->pier;
l->last->pier=n;
l->last->pier->next=n;
l->length++;
return 1;
}
int DeleteNode(LIST *l,int index)
{
NODE *p = NULL;
int i;
if(NULL == l || index <1 || index>l->length)
return 0;
while(i < l->length)
{
i++;
if(i == index)
break;
p = p->next;
}
p->pier->next = p->next;
p->next->pier = p->pier;
free(p->data);
free(p);
return 1;
}
void PrintData(void *data)
{
int *d =(int *)data;
printf("data = %d",*d);
}
void PrintList(LIST *l,int page,int preP,void (*PrintData)(void *))
{
int start,end,i=0;
NODE *p = NULL;
if(l == NULL || PrintData == NULL)
return;
start = (page - 1)*preP + 1;
end = page * preP;
p = l->head->next;
while(i < l->length && p->next != NULL)
{
i++;
if(i == start)
break;
p = p->next;
}
for(;i < end && p->next != NULL;i++)
{
PrintData(p->data);
p = p->next;
}
}
void main(int argc, char* argv[])
{
int i;
LIST *list = InitList();
for(i=0;i<5;i++)
InsertNode(list,&a[i],sizeof(a[i]));
PrintList(list,1,4,PrintData);
}