Linux常见数据结构之链表

本文详细介绍了链表的基本概念、数据结构组成及在C语言中的具体实现方法,包括单链表的插入、删除操作,以及双链表的初始化、节点插入和删除等。此外,还展示了如何将有序链表逆序以及合并两个有序链表的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表是一种常见的重要数据结构,它可以动态地进行存储分配,根据需要开辟内存单元,还可以方便地实现数据的增加和删除。链表中的每个元素都由两部分组成:数据域和指针域。

     其中,数据域用来存储数据元素的信息,指针域用来存储该元素的直接后继元素的位置。其整体结构就是用指针相链接起来的线性表,如下图所示:

下面通过实例说明单链表使用方法,在该实例中可实现在任意位置增加或删除结点。

#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);
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值