图解无头单向非循环链表和带头双向循环链表


链表是一种重要的数据结构,其概念:链表是一种 物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的

这里介绍两种链表:

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
  1. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。

单链表(单向不带头)

在这里插入图片描述

数据节点和头结点

在这里插入图片描述

typedef int Data;        //数据类型
typedef struct lists{
    
        //自定义单链表结构体
	Data _data;
	struct lists* _next;
}lists;

//自定义头结点
typedef struct firstlist{
    
    //用来找到并操作链表,必须从头开始
	struct lists* _head;
}firstlist;

新增节点函数和初始化

//结构体初始化
void init(firstlist* flist){
    
    
	if (flist == NULL){
    
    
		return flist;
	}
	flist->_head = NULL;   //数据设为空
}

lists* xinzeng(Data _data){
    
    //将一个数据传入一个新链表,返回新链表的地址
	lists* newlist = (lists*)malloc(sizeof(lists));
	newlist->_data = _data;
	newlist->_next = NULL;
	return newlist;
}

基本操作

1.尾插

在这里插入图片描述

//尾插
void weicha(firstlist* lit,Data data){
    
    //将data尾插到lit链表中
	//传firstlist是因为知道头结点地址就可以操作链表了
	if (lit == NULL){
    
    //如果是空链表直接返回null
		return;
	}
	//空链表插入第一个数据
	if (lit->_head == NULL){
    
    
		lit->_head = xinzeng(data);
	}
	else{
    
    //不是空链表则需要遍历
		lists* list = lit->_head;
		//因为_head是第一个元素的地址,所以要lists*
		while (list->_next != NULL){
    
    
			list = list->_next;
		}
		list->_next = xinzeng(data);
	}
}

2.尾删

在这里插入图片描述

//尾删
void weishan(firstlist* flist){
    
    
	if (flist == NULL||flist->_head==NULL){
    
    
		return;
	}
	//用两个变量one 和two来操作
	lists* one = flist->_head;
	lists* two = NULL;
	if (one->_next != NULL){
    
    
		two = one;
		one = one->_next;
	}
	free(one);
	if (two == NULL){
    
    //这种是只有头节点,two就没变
		flist->_head = NULL;
	}
	else{
    
    
		two->_next = NULL;
	}
}

3.头插

在这里插入图片描述

//头插
void toucha(firstlist* flist,Data data){
    
    
	if (flist == NULL){
    
    
		return;
	}
	if (flist->_head == NULL){
    
    
		flist->_head = xinzeng(data);
	}
	else{
    
    
		lists* b = xinzeng(data);
		b->_next = flist->_head;
		flist->_head = b;	
	}
}

4.头删

//头删
void toushan(firstlist* list){
    
    
	if (list==NULL){
    
    
		return;
	}
	if (list->_head == NULL){
    
    
		return;
	}
	else{
    
    
		struct lists* next = list->_head->_next;
		free(list->_head);
		list->_head = next;
	}
}

5.任意位置新增节点

//在哪新增一个节点
void jiaru(lists* a,Data data){
    
    //用不到头节点所以直接操作
	lists* list = xinzeng(data);
	list->_next = a->_next;
	a->_next = list;
}

6.任意位置删除

//删除那个位置的下一个
void shanchu(lists* a,Data data){
    
    
	lists* next = a->_next;
	if (next == NULL){
    
    
		return;
	}
	lists* next2 = a->_next->_next;
	free(next);
	a->next=next2;
}

7.寻找数据

lists* find(firstlist* flist, Data data){
    
    
	if (flist == NULL || flist->_head == NULL){
    
    
		return;
	}
	while (flist->_head){
    
    
		if (flist->_head->_data == data){
    
    
			return flist->_head;
		}
		else{
    
    
			flist->_head = flist->_head->_next;//思路类似于头删,但没有free就不是删除
		}
	return NULL;//一直没找到返回空
	}
}

8.销毁链表

//销毁链表
void xiaohui(firstlist* flist){
    
    
	if (flist == NULL || flist->_head == NULL){
    
    
		return;
	}
	while (flist->_head){
    
    //循环头删
		flist->_head = flist->_head->_next;
		free(flist->_head);
	}
	flist->_head = NULL;
}

带头双向循环链表

在这里插入图片描述
其中头结点没有数据,所以
空表:
在这里插入图片描述非空表:
在这里插入图片描述

数据节点和头节点

typedef int Data;
typedef struct lists{
    
    //数据节点
	Data _data;
	struct lists* _prev;
	struct lists* _next;
}lists;

typedef struct headlist{
    
    //头结点
	struct lists* _head;
}headlist;

在这里插入图片描述

新增节点函数和初始化

1.新增节点

lists* create(Data data){
    
    //创造新节点
	lists* new = (lists*)malloc(sizeof(lists));
	new->_data = data;
	new->_next = NULL;
	new->_prev = NULL;
	return new;
}

2.初始化链表

void init(headlist* hlist){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	hlist->_head = create(0);
	hlist->_head->_next = hlist->_head->_prev = hlist->_head;
}

基本操作(删除和增加)

1.尾插

在这里插入图片描述

//尾插
void weicha(headlist* hlist, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	//_head .....  last + new
	lists* new = create(data);
	lists* last=hlist->_head->_prev;
	last->_next=new;
	new->_prev = last;
	new->_next = hlist->_head;
	hlist->_head->_prev = new;
}

2.尾删

在这里插入图片描述

//尾删
void weishan(headlist* hlist){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	if (hlist->_head->_next = hlist->_head->_prev = hlist->_head){
    
    
		return;
	}
	lists* last = hlist->_head->_prev;//最后一个
	lists* prev=hlist->_head->_prev->_prev;//倒数第二个
	free(last);
	hlist->_head->_prev = prev;
	prev->_next = hlist->_head;
}

3.头插

在这里插入图片描述

//头插
void toucha(headlist* hlist, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	lists* new=create(data);
	lists* old=hlist->_head->_next;
	//_head   (new)   old
	hlist->_head->_next = new;
	new->_prev = hlist->_head;
	new->_next = old;
	old->_prev = new;
}

4.头删

在这里插入图片描述

//头删
void toushan(headlist* hlist){
    
    
	if (hlist->_head->_next = hlist->_head->_prev = hlist->_head){
    
    
		return;
	}
	if (hlist == NULL){
    
    
		return;
	}
	lists* first = hlist->_head->_next;
	lists* second = hlist->_head->_next->_next;
	//_head  first(删)  second
	second->_prev = hlist->_head;
	hlist->_head->_next = second;
	free(first);
}

5.在任意位置删除

在这里插入图片描述

//在任意位置删除
void anywheredelete(headlist* hlist, lists* list){
    
    
	if (hlist->_head = list){
    
    
		return;
	}
	if (hlist == NULL){
    
    
		return;
	}
	//prev  list(删掉)  next
	lists* prev = list->_prev;
	lists* next = list->_next;

	prev->_next = next;
	next->_prev = prev;
	free(list);
}

6.在任意位置增加

在这里插入图片描述

//在任意位置增加
void anywhereadd(headlist* hlist, lists* list, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	//prev new  list
	lists* new = create(data);
	lists* prev = list->_prev;
	prev->_next = new;
	new->_prev = prev;
	new->_next = list;
	list->_prev = new;
}

顺序表和链表的评价

顺序表链接:link

1.顺序表空间连续,所以支持随机访问.
链表空间不连续,不支持随机访问.

2.顺序表插入删除效率低
链表任意位置插入删除高效

源代码

单链表

#include<stdio.h>
#include<windows.h>
typedef int Data;        //数据类型
typedef struct lists{
    
        //自定义单链表结构体
	Data _data;
	struct lists* _next;
}lists;

//自定义头结点
typedef struct firstlist{
    
    //用来找到并操作链表,必须从头开始
	struct lists* _head;
}firstlist;

//结构体初始化
void init(firstlist* flist){
    
    
	if (flist == NULL){
    
    
		return flist;
	}
	flist->_head = NULL;   //数据设为空
}

lists* xinzeng(Data _data){
    
    //将一个数据传入一个新链表,返回新链表的地址
	lists* newlist = (lists*)malloc(sizeof(lists));
	newlist->_data = _data;
	newlist->_next = NULL;
	return newlist;
}

//尾插
void weicha(firstlist* lit,Data data){
    
    //将data尾插到lit链表中
	//传firstlist是因为知道头结点地址就可以操作链表了
	if (lit == NULL){
    
    //如果是空链表直接返回null
		return;
	}
	//空链表插入第一个数据
	if (lit->_head == NULL){
    
    
		lit->_head = xinzeng(data);
	}
	else{
    
    //不是空链表则需要遍历
		lists* list = lit->_head;
		//因为_head是第一个元素的地址,所以要lists*
		if (list->_next != NULL){
    
    
			list = list->_next;
		}
		list->_next = xinzeng(data);
	}
}

//尾删
void weishan(firstlist* flist){
    
    
	if (flist == NULL||flist->_head==NULL){
    
    
		return;
	}
	//用两个变量one 和two来操作
	lists* one = flist->_head;
	lists* two = NULL;
	if (one->_next != NULL){
    
    
		two = one;
		one = one->_next;
	}
	free(one);
	if (two == NULL){
    
    //这种是只有头节点,two就没变
		flist->_head = NULL;
	}
	else{
    
    
		two->_next = NULL;
	}
}

//头插
void toucha(firstlist* flist,Data data){
    
    
	if (flist == NULL){
    
    
		return;
	}
	if (flist->_head == NULL){
    
    
		flist->_head = xinzeng(data);
	}
	else{
    
    
		lists* b = xinzeng(data);
		b->_next = flist->_head;
		flist->_head = b;	
	}
}

//头删
void toushan(firstlist* list){
    
    
	if (list==NULL){
    
    
		return;
	}
	if (list->_head == NULL){
    
    
		return;
	}
	else{
    
    
		struct lists* next = list->_head->_next;
		free(list->_head);
		list->_head = next;
	}
}

//在哪新增一个节点
void jiaru(lists* a,Data data){
    
    //用不到头节点所以直接操作
	lists* list = xinzeng(data);
	list->_next = a->_next;
	a->_next = list;
}

//删除那个位置的下一个
void shanchu(lists* a,Data data){
    
    
	lists* next = a->_next;
	if (next == NULL){
    
    
		return;
	}
	lists* next2 = a->_next->_next;
	next = next2;
	free(next);
}

//找到某数据
lists* find(firstlist* flist, Data data){
    
    
	if (flist == NULL || flist->_head == NULL){
    
    
		return;
	}
	while (flist->_head){
    
    
		if (flist->_head->_data == data){
    
    
			return flist->_head;
		}
		else{
    
    
			flist->_head = flist->_head->_next;//思路类似于头删,但没有free就不是删除
		}
	return NULL;//一直没找到返回空
	}
}

//销毁链表
void xiaohui(firstlist* flist){
    
    
	if (flist == NULL || flist->_head == NULL){
    
    
		return;
	}
	while (flist->_head){
    
    //循环头删
		flist->_head = flist->_head->_next;
		free(flist->_head);
	}
	flist->_head = NULL;
}

双向链表

#include<stdio.h>
typedef int Data;
typedef struct lists{
    
    //数据节点
	Data _data;
	struct lists* _prev;
	struct lists* _next;
}lists;

typedef struct headlist{
    
    //头结点
	struct lists* _head;
}headlist;

lists* create(Data data){
    
    //创造新节点
	lists* new = (lists*)malloc(sizeof(lists));
	new->_data = data;
	new->_next = NULL;
	new->_prev = NULL;
	return new;
}

void init(headlist* hlist){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	hlist->_head = create(0);
	hlist->_head->_next = hlist->_head->_prev = hlist->_head;
}

//尾插
void weicha(headlist* hlist, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	//_head .....  last + new
	lists* new = create(data);
	lists* last=hlist->_head->_prev;
	last->_next=new;
	new->_prev = last;
	new->_next = hlist->_head;
	hlist->_head->_prev = new;
}

//尾删
void weishan(headlist* hlist){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	if (hlist->_head->_next = hlist->_head->_prev = hlist->_head){
    
    
		return;
	}
	lists* last = hlist->_head->_prev;//最后一个
	lists* prev=hlist->_head->_prev->_prev;//倒数第二个
	free(last);
	hlist->_head->_prev = prev;
	prev->_next = hlist->_head;
}

//头插
void toucha(headlist* hlist, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	lists* new=create(data);
	lists* old=hlist->_head->_next;
	//_head   (new)   old
	hlist->_head->_next = new;
	new->_prev = hlist->_head;
	new->_next = old;
	old->_prev = new;
}

//头删
void toushan(headlist* hlist){
    
    
	if (hlist->_head->_next = hlist->_head->_prev = hlist->_head){
    
    
		return;
	}
	if (hlist == NULL){
    
    
		return;
	}
	lists* first = hlist->_head->_next;
	lists* second = hlist->_head->_next->_next;
	//_head  first(删)  second
	second->_prev = hlist->_head;
	hlist->_head->_next = second;
	free(first);
}

//在任意位置删除
void anywheredelete(headlist* hlist, lists* list){
    
    
	if (hlist->_head = list){
    
    
		return;
	}
	if (hlist == NULL){
    
    
		return;
	}
	//prev  list(删掉)  next
	lists* prev = list->_prev;
	lists* next = list->_next;

	prev->_next = next;
	next->_prev = prev;
	free(list);
}

//在任意位置增加
void anywhereadd(headlist* hlist, lists* list, Data data){
    
    
	if (hlist == NULL){
    
    
		return;
	}
	//prev new  list
	lists* new = create(data);
	lists* prev = list->_prev;
	prev->_next = new;
	new->_prev = prev;
	new->_next = list;
	list->_prev = new;
}

猜你喜欢

转载自blog.csdn.net/zhaocx111222333/article/details/112279706