C语言数据结构单链表之温故而知新

抛弃繁杂的定义,以实用,实战的角度来学习数据结构,这将使得数据结构的学习非常的简单。

前面已经学习了单链表的创建操作:http://blog.csdn.net/morixinguan/article/details/68951912

这节,将单链表温习的笔记共享出来,然后写一个例子,以防自己忘记。

1、单链表的数据结构的定义:

创建节点函数原型可定义如下:

struct list *create_node(int data) ;
如何创建单链表的节点,主要分以下步骤:
(1)给当前的每个节点的数据结构配置定量的空间大小
   ep : struct list *node = malloc(sizeof(struct list));
(2)清节点数据(由于结构体变量在未初始化的时候,数据是脏的)
   ep : memset(node,0,sizeof(struct list));
(3)给节点初始化数据
   ep : node->id = data ;
(4)将该节点的指针域设置为NULL
   ep : node->next = NULL ;

3、单链表的尾插:
尾插节点函数原型可定义如下:

如何将当前链表和新的节点相连接?只要实现:
header->next = new 

尾插流程如下:

(1)获取当前节点的位置,也就是访问头节点
   ep : struct list *p = header ;
(2)判断是否为最后一个节点,如果不是,移动到下一个节点,如果是,将数据插入尾部。
   ep : while(NULL != p->next) p = p->next ;
	    p->next = new ;

4、单链表的头插

很好理解,头插就是把新的节点插在原来的节点和原来节点的下一个节点之间的一个节点。如图,新的节点插在头节点和节点1。
所以可以推出头插流程如下:

(1)获取当前节点的位置,也就是访问头节点
	ep : struct list *p = header ;
(2)新的节点的下一个节点设置为原来头节点的下一个节点(第一个节点)
    ep : new->next = p->next ;
(3)原来的头节点的下一个节点设置为现在新插入的头节点
	ep : p->next = new ;

5、单向链表的遍历

      如图为一条单向链表的模型,看图知道该链表由头节点和若干个节点组成,最后一个节点(尾节点)为NULL 。
从图中可以得出信息,如果我们要打印出各个节点的数据,要考虑以下问题:

(1)需要打印头节点吗?(头节点肯定是不用打印的,因为这是我们为了操作方便而设置的一个节点)。
(2)这条链表有多少个节点我们怎么知道?(通过判断该链表是否已经到达了尾节点,标志就是NULL)

那么可以得到流程如下:

(1)获取当前节点的位置,也就是访问头节点
	ep : struct list *p = header ;
(2)由于头节点我们不需要去打印它,这时候,初始化打印的节点需要从第一个节点开始。
	ep : p = p->next ;
(3)判断是否为最后一个节点,如果不是,先打印第一个节点的数据(1),然后移动到下一个节点(2),重复这两个步骤。
   如果是最后一个节点,直接打印数据即可。
	while(NULL != p->next){ printf("node:%d\n",p->data) ; p = p->next ;}
	printf("node:%d\n",p->data);
	当然还可以一句代码解决,这样就达到了先偏移,后取数据。
	while(NULL != p->next){ p = p->next ; printf("node:%d\n",p->data) ; }

6、单向链表的删除

删除节点的函数原型可定义如下:
int detele_list_node(struct list *pH , int data);
单向链表的删除要考虑两种情况,一种的普通节点的删除(当然,头节点不能算)
还有一种是尾节点的前一个节点的删除情况,注意,删除完节点还需要释放对应节点的内存空间。

删除节点的设计流程:

(1)先定义两个指针,一个表示当前的节点,另一个表示当前节点的上一个节点。
	ep : struct list *p = header ;  //当前节点
		 struct list *prev = NULL ; //当前节点的上一个节点
(2)遍历整个链表,同时保存当前节点的前一个节点
    ep : while(NULL != p->next)
		{
		  //保存了当前的节点的前一个节点
		  prev = p ;
		  //保存当前偏移的节点
		  p = p->next ;
		  return 0 ;
		}
(3)在遍历的过程中查找要删除的数据
	ep : while(NULL != p->next)
		{
		  //保存了当前的节点的前一个节点
		  prev = p ;
		  //保存当前偏移的节点
		  p = p->next ;
		  //查找到了数据
		  if(p->id == data)
		  {

		  }
		  return 0 ;
		}
(4)查找到了数据后,分两种情况删除
	ep : 普通节点的删除
		if(p->id == data)
		{
			prev->next = p->next ;
			free(p);
		}
	ep : 考虑尾节点的下一个节点为NULL的节点删除
		if(p->id == data)
		{
			if(p->next == NULL)
			{
				prev->next = NULL ;
				free(p);
			}
		}

5、单向链表的逆序操作

逆序步骤:

流程咱们基本搞懂了,下面写一个程序,这将会变得非常非常的简单。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct slist
{
	int id ;
	struct slist *next ;
}L;

//创建一个节点
L *create_node(int data)
{
	//给每个节点分配结构体一样的空间大小
	L *p = malloc(sizeof(L));
	if(NULL == p)
	{
		printf("malloc error!\n");
		return NULL ;
	}
	//由于结构体在未初始化的时候一样是脏数据,所以要清
	memset(p,0,sizeof(L));
	//初始化第一个节点
	p->id = data ;
	//将节点的后继指针设置为NULL
	p->next = NULL ;
}

//链表的尾插
void tail_insert(L *pH , L *new)
{
	//获取当前的位置
	L *p = pH ;
	//如果当前位置的下一个节点不为空
	while(NULL != p->next)
	{
		//移动到下一个节点
		p = p->next ;
	}
	//如果跳出以上循环,所以已经到了NULL的这个位置
	//此时直接把新插入的节点赋值给NULL这个位置
	p->next = new ;
}

//链表的头插
void top_insert(L *pH , L *new)
{
	L *p = pH ;
	new->next = p->next ;
	p->next = new ;
}

//链表的遍历
void Print_node(L *pH)
{
	//获取当前的位置
	L *p = pH ;
	//获取第一个节点的位置
	p = p->next ;
	//如果当前位置的下一个节点不为空
	while(NULL != p->next)
	{
		//(1)打印节点的数据
		printf("id:%d\n",p->id);
		//(2)移动到下一个节点,如果条件仍为真,则重复(1),再(2)
		p = p->next ;
	}
	//如果当前位置的下一个节点为空,则打印数据
	//说明只有一个节点
	printf("id:%d\n",p->id);
}

//删除链表中的节点
int detele_list_node(L * pH , int data)
{
	//获取当前头节点的位置
	L *p = pH ;
	L *prev = NULL;
	while(NULL != p->next)
	{
		//保存当前节点的前一个节点的指针
		prev = p ;
		//然后让当前的指针继续往后移动
		p = p->next ;
		//判断,找到了要删除的数据
		if(p->id == data)
		{
			//两种情况,一种是普通节点,还有一种是尾节点
			if(p->next != NULL)  //普通节点的情况
			{
				prev->next = p->next ;
				free(p);
			}
			else //尾节点的情况
			{
				prev->next = NULL ; //将这个尾节点的上一个节点的指针域指向空
				free(p);
			}
			return 0  ;
		}
	}
	printf("没有要删除的节点\n");
	return -1 ;
}

void trave_list(L * pH)
{
	//保存第一个节点的位置
	L *p = pH->next;
	L *pBack;
	int i = 0 ;
	if(p->next == NULL || p == NULL)
		return ;

	while(NULL != p->next) //遍历链表
	{
		//保存第一个节点的下一个节点
		pBack = p->next ;
		//找到第一个有效节点,其实就是头指针的下一个节点
		if(p == pH->next)
		{
			//第一个有效节点就是最后一个节点,所以要指向NULL
			p->next = NULL ;
		}
		else
		{
			/*
			new->next = p->next ;
			p->next = new ;
			*/
			p->next = pH->next ; //尾部连接
		}
		pH->next = p ; //头部连接
		p = pBack ; //走下一个节点
	}
	top_insert(pH,p); //插入最后一个节点
}

int main(int argc , char **argv)
{
	//创建第一个节点
	int i ;
	L *header = create_node(0);
	for(i = 1 ; i < 10 ; i++)
	{
		tail_insert(header,create_node(i));
	}
	Print_node(header);
	detele_list_node(header,5);
	putchar('\n');
	Print_node(header);
	putchar('\n');
	trave_list(header);
	Print_node(header);
	return 0 ;
}

运行结果:

时间: 2024-09-15 05:12:01

C语言数据结构单链表之温故而知新的相关文章

c语言 数据结构-单链表的就地逆置 辅助空间为O(1)

问题描述 单链表的就地逆置 辅助空间为O(1) 求大神给个单链表的就地逆置 要不开拓辅助空间 原谅我没有C币 解决方案 struct Node{ int value; Node *next; }; void reverse(Node* head){ Node *prev, *cur, *next; cur = head; prev = NULL; while(cur != NULL){ next = cur->next; cur->next = prev; prev = cur; cur =

插入删除-数据结构单链表的插入与删除

问题描述 数据结构单链表的插入与删除 设单链表某一节点为p,怎样在p节点前插入一个结点?怎样删除p节点自身?(要求:用Java语言写出具体程序语言) 解决方案 这个主要是定位问题,只要能定到节点p的位置就好. List list = new LinkedList(); list.add(list.indexOf(p), "插入内容");//由于是链表结构,所以数据插入位置的后方下标自动后移 list.remove(list.indexOf(p));//删除p节点 就是这个思路,不知道对

C语言之单链表的插入、删除与查找_C 语言

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.要实现对单链表中节点的插入.删除与查找的功能,就要先进行的单链表的初始化.创建和遍历,进而实现各功能,以下是对单链表节点的插入.删除.查找功能的具体实现: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef int ElemType; /** *链表通用类型 *ElemType 代表自定义的数据类型 *struct

数据结构 单链表-求大神给我讲讲数据结构单链表和队列

问题描述 求大神给我讲讲数据结构单链表和队列 帮我彻底分析下两种结构,感激不尽多谢大神了 解决方案 单链表和队列是两个层次的事情. 单链表是一种基本的表示一个线性表的方式,它记录下当前节点的数据和指向下一个节点的指针.因此一环一环可以得到整个数据.除了单链表,我们还有数组.双向链表.循环链表等. 队列是一种先进先出的数据结构,它高于链表一个层次,这是说,你可以用链表实现队列(当然也可以用数组或者别的).另外还有先进后出的数据结构(堆栈)等. 解决方案二: 具体你可以google下wikipedi

c语言-C语言建立单链表的问题

问题描述 C语言建立单链表的问题 #include<stdio.h> #include<stdlib.h> struct node { int num; int L; struct node *next; }; typedef struct node LN; typedef struct { int num1[100]; int L1; }S; void Creat1(S &p); void Creat(LN *p); void main() { S p; LN *h; p

浅谈PHP链表数据结构(单链表)_php实例

链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个程序运行时,内存分成五个区(堆区,栈区,全局区,常量区,代码区) 规定:基本数据类型,一般放在栈区 复合数据类型,比如对象,放在堆区 定义一个类Hero 定义成员属性排名 $no 定义成员属性姓名 $name 定义成员属性昵称 $nickname 定义成员属性 $next,是一个引用,指向下一个Hero对象 定义构造函数,传递参数:

用C语言实现单链表的各种操作(二)_C 语言

上一篇文章<用C语言实现单链表的各种操作(一)>主要是单链表的一些最基本的操作,下面,主要是一些其他的典型的算法和测试程序. 复制代码 代码如下: /* 对单链表进行排序处理*/struct LNode *sort(struct LNode *head){  LinkList *p;  int n,i,j;  int temp;  n = ListLength(head);  if(head == NULL || head->next == NULL)    return head; 

数据结构 单链表-帮我看看下面的程序哪里出错了,刚从数据结构学的单链表,运行不了

问题描述 帮我看看下面的程序哪里出错了,刚从数据结构学的单链表,运行不了 就简单的取值 插入 删除 合并 #include #include #include typedef struct LNode { int num; struct LNode *next; }LNode,*LinkList; void InitiList(LinkList L) { L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; } void LocateElem(Link

用C语言实现单链表的各种操作(一)_C 语言

最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的<数据结构>(C 语言版),中的例子和后面的习题进行改编的.首先,是单链表的各种实现,其中,包含了一些常考的知识点.例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现.下面这个是单链表的结构体的定义: 复制代码 代码如下: typedef struct LNode{ ElemType data; struct LNode *next;}LinkList; 下面的基本的单链表的操作:其