c语言实现单向链表和双向链表

链表:它是一种物理储存单元上的非连续,非顺序的储存结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表由一系列结点组成,每个结点包括两部分,一个是储存数据元素的数据域,一个是储存下一个结点地址的指针域

顺序表:顺序表是使用数组存储线性的元素,因为逻辑上相邻的元素物理上也相邻,所以插入删除需要移动后面的所有元素,但是链表使用指针来表达后面结点的逻辑关系,所以插入和删除只需要修改指针即可。

链表可以解决几个数组无法解决的问题:数组无法储存多种类型的数据,数组中元素的个数无法改变,数组移动元素时其他元素也要跟着移动

链表实现原理: 头指针指向了链表的第一个节点,然后第一个节点中的指针指向了下一个节点,下一个节点指向下下个节点,直到最后一个节点需要指向Null

#include <stdio.h>
#include <stdlib.h>

struct linklist_node{  // 以结构的形式来声明一个链表节点
	int data;  // 节点的数据域,用于存储数据
	struct linklist_node * next;  // 节点的指针域,指向下一个类型为linklist_node的节点
};
typedef struct linklist_node single_node; // 这里节点结构被声明为single_node了

// 下面是创建一个链表节点的函数
single_node * create_single_node(int data){
	single_node * node = NULL;  // 首先定义一个指向节点类型的指针
	node = (single_node *)malloc(sizeof(single_node));  // 为node动态分配内存
	memset(node, 0, sizeof(single_node)); // 为新分配的内存进行初始化
	
	node -> data = data;  // 数据域赋值
	node -> next = NULL;  // 指针域赋值,指向空
	return node;  // 返回一个指向node类型的指针
}

// 下面是主函数
int main(void){
	int data = 1;
	single_node * node_ptr = create_single_node(data);  // 创建一个节点,得到一个节点指针
	free(node_ptr); // 释放内存
	return 0;
}

上面的node_ptr其实是定义的一个头指针,然后它指向拥有数据域和指针域的节点,然后该节点指向NULL。


接下来,我们首先用一段主函数来描述我们想用各种函数完成的事儿

int main(int argc, char **argv){
	int i;
	single_node * header = create_single_node(0); // 创建第一个节点
	for(i = 1; i < 10; i++){
		tail_insertion(header, create_single_node(i));
	} // 尾插一堆元素
	top_insertion(header, create_single_node(100);
	print_node(header);  // 打印所有的元素
	delete_single_node(header, 5);  // 删除指定值的元素
}

链表的尾插:

void tail_insertion(single * header, single * new){
	single_node * current;
	current = header;
	while(current->next != NULL){
		current = current->next;  // 这里直到找到最后一个节点
	}
	current->data = new->id;
	current->next = NULL;
}

链表的头插:

void top_insertion(single_node * header, single * new){
	single_node * current;
	current = header;
	new -> next = current -> next;  // 这里要先把新节点的下一个指向第二个节点,不然可以反过来就知道错误了
	current -> next = new;
}	

链表元素的打印:

void print_node(single_node * header){
	single_node * current = header;
	current = current -> next;  // 获取第一个节点的位置,因为header是头指针没有值的
	while(current -> next != NULL){
		printf("data is %d", current -> data);
		current = current -> next;
	}
}

删除链表中的元素:

int delete_single_node(single_node * header, int data){
	single_node * current = header;  // 设置当前位置为头指针
	single_node * prev = NULL;  // 记录前一个节点的位置,最一开始为空
	while(current -> next != NULL){
		prev = current;  // 第一步将prev设置为头指针了
		current = current -> next;  // 第一步将current设置为第一个节点了
		if(current -> data == data){
			if (current -> next == NULL){   // 当当前节点为最后一个节点时,该节点next应该为空
				prev -> next = NULL;
			}
			else{  // 这是普通节点
				prev -> next = current -> next;
			}
			free(p);
		}
	}
	return 0}

双向链表

单链表存在一定的弊端,查找数据和删除数据的时候比较麻烦,而双链表就可以解决这个弊端,双链表既可以往前遍历,也可以往后遍历;所以双链表的节点相当于data加上两个指针,一个指向前面的节点,一个指向后面的节点。

struct double_linklist_node{
	int data;
	struct double_linklist_node * prev;
	struct double_linklist_node * next;
}
typedef struct double_linklist_node single_node;

single_node * create_single_node(int data){haishi shnme size (of 
	single_node * node = (single_node *)malloc(sizeof(single_node));
	memset(node, 0, sizeof(single_node));
	node -> data = data;
	node -> prev = NULL;
	node -> next = NULL;
	return node;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章