Chapter 3(线性表)



1.单链表
//单链表代码,手打纯手工


//***********************************link.h***********************************
#ifndef LINK_H
#define LINK_H


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


typedef int datatype;

typedef struct link
{
	datatype data;
	struct link *next;


}Node,*Link;


//创建单链表
Link linkCreate();


//获得链表长度
size_t length(Link link);

//判断链表是否为空
bool isEmpty(Link link);

//获得第i个前的地址
Node *addressFront(Link link,size_t i);

//获取第i个节点的值
datatype getElement(Link link,size_t i);


//查找元素num是否存在
bool isExist(Link link,datatype num);

//插入元素
bool insert(Link link,size_t i,datatype num);

//在链表头插入元素
bool pushFront(Link link,datatype num);

//在链表尾插入元素
bool pushBack(Link link,datatype num);

//删除第i个元素
bool deleteI(Link link,size_t i);


//删除包含元素num的第一个节点
bool deleteNum(Link link,datatype num);

//遍历打印整个链表
void travel(Link link);

//清空链表
bool clear(Link link);

//销毁链表
bool destroy(Link link);

//链表翻转
bool reverse(Link link);

//链表指定长度反转
void reverseN(Link link,int n);




#endif //LINK_H



//*************************link.c****************************************
#include "link.h"




//创建单链表头
Link linkCreate()
{
	Node *p = (Node *)malloc(sizeof(Node));
	p->next = NULL;
	return p;
}


//获得链表长度
size_t length(Link link)
{
	size_t count = 0;
	Node *node = link->next;
	while(node)
	{
		count++;
		node = node->next;
	}
	return count;
}

//判断链表是否为空
bool isEmpty(Link link)
{
	if(NULL == link->next)return true;
	return false;
}


//获得第i个前的地址,供内部使用
Node *addressFront(Link link,size_t i)
{
	if(NULL == link)return NULL;//头节点为空,返回NULL
	
	if(i > (length(link)+1))return NULL;//i越界,len+1是可取的,相当于最后加上这个数,i不能为0.返回于NULL

	if(isEmpty(link))return link;//当链表为空时,返回头节点地址

	Node *pre  = link; //保存前一个节点的地址
	Node *curr = link->next;
	for(size_t j = 1;j < i;j++)
	{
		pre  = curr;
		curr = curr->next; 
	}

	return pre;
}

//获取第i个节点的值
datatype getElement(Link link,size_t i)
{
	Node *node = addressFront(link,i);
	return node->next->data;
}


//查找元素num是否存在
bool isExist(Link link,datatype num)
{
	if(NULL == link)return false;

	Node *node = link->next;
	
	while(node)
	{
		if(num == node->data)return true;
		node = node->next;
	}
	return false;
}

//插入元素
bool insert(Link link,size_t i,datatype num)
{
	if(NULL == link)return false;
	if(i > (length(link)+1)||i <= 0)return false;


	Node *pre  = addressFront(link,i);//获得第i-1个节点的地址
	Node *node = (Node *)malloc(sizeof(Node));//申请内存存放新节点
	Node *save = pre->next; //将原来的第i个节点的地址保存在save中
	
	pre->next = node; //将原来的第i-1个节点指向新节点

	node->data = num; //为新节点的数据域赋值
	node->next = save;//将新节点指向原来的第i个节点
	
	return true;
}

//在链表头插入元素
bool pushFront(Link link,datatype num)
{
	return insert(link,1,num);
}

//在链表尾插入元素
bool pushBack(Link link,datatype num)
{
	return insert(link,length(link)+1,num);
}

//删除第i个元素
bool deleteI(Link link,size_t i)
{
	if(NULL == link)return false;
	if(i>length(link) || i<=0)return false;


	Node *pre = addressFront(link,i);
	Node *node= pre->next;

	pre->next = node->next;
	free(node);
	node = NULL;
	return true;
}


//删除包含元素num的第一个节点
bool deleteNum(Link link,datatype num)
{
	if(NULL == link)return false;
	
	Node *pre  = link;
	Node *curr = link->next;
	while(curr)
	{
		if(num == curr->data)
		{
			pre->next = curr->next;
			free(curr);
			curr = NULL;
			return true;
		}
		pre = curr;
		curr= curr->next;
	}

	return false;
}

//遍历打印整个链表
void travel(Link link)
{
	if(NULL == link)return;

	Node *node = link->next;
	while(node)
	{
		printf("%d ",node->data);
		node = node->next;
	}
	printf("
");
}

//清空链表
bool clear(Link link)
{
	if(NULL == link)return false;

	Node *node = link->next;//从头节点开始释放
	
	while(node)
	{
		Node *temp = node->next;//保存下一个节点的地址
		free(node);//释放当前节点
		node = temp;//将下一个节点地址赋给node
	}
	link->next = NULL;//头节点指向空

	return true;
}

//销毁链表
bool destroy(Link link)
{
	if(NULL == link)return false;

	clear(link);
	free(link);
	link = NULL;
	return true;
}


//链表翻转
bool reverse(Link link)
{
	if(NULL == link)return false;

	Node *pre = link->next;
	Node *curr= pre->next;

	while(curr)
	{
		Node *temp = curr->next;//保存当前节点的下一个节点地址
		curr->next = pre;//将当前节点指向上一个节点

		pre = curr;//将上一个节点指向当前节点
		curr= temp;//将当前节点指向喜爱一个节点
	}
	
	link->next->next = NULL;//将原来第一个节点指向空
	link->next = pre;//将头节点指向原来的最后一个节点
	return true;
}


//链表指定长度反转工具
void reverseTool(Node *prev,Node *curr,int num)
{
	if(NULL == curr)return;

	Node *prevNode = curr;
	Node *currNode = curr->next;

	int count = 1;
	while(currNode)
	{
		Node *nextNode = currNode->next;
		currNode->next = prevNode;
		prevNode = currNode;
		currNode = nextNode;
		count++;

		if(num == count)
		{
			Node *temp = prev->next;
			prev->next->next =currNode;
			prev->next = prevNode;
			reverseTool(temp,currNode,num);
			return;
		}
	}

	prev->next->next = currNode;
	prev->next = prevNode;
}

//链表指定长度反转
void reverseN(Link link,int n)
{	
	Node *node = link->next;
	reverseTool(link,node,n);
}



//************************linkTest.c*****************************************


#include "link.h"

int main(int argc,char *argv[])
{
	Link head = linkCreate();
	travel(head);
	insert(head,1,77);
	travel(head);
	insert(head,1,777);
	travel(head);
	insert(head,3,7777);
	travel(head);
	printf("length = %d
",length(head));

	pushFront(head,52);
	travel(head);
	printf("length = %d
",length(head));


	pushBack(head,00);
	travel(head);
	printf("length = %d
",length(head));

	//deleteNum(head,777);
	//deleteI(head,2);
	travel(head);
	printf("length = %d
",length(head));
	

	printf("-----
");
	reverseN(head,2);
	//clear(head);
	travel(head);
	return 0;
}

2.静态链表
//静态链表代码,纯手打

//********************static_link.h***********************
#ifndef STATIC_LINK_H
#define STATIC_LINK_H

#include <stdio.h>
#include <stdbool.h>
#define MAXSIZE 1000

typedef int datatype;


typedef struct Static_linklist
{
	datatype data;
	int curr;
}Node,static_link[MAXSIZE];


//初始化静态链表
bool InitList(static_link link);



//获取链表长度
size_t length(static_link link);

//Malloc_SLL若备用链表非空,则返回分配的节点下标,否则返回0
int Malloc_SLL(static_link link);

//Free_SSL将下标为K的空闲节点回收到备用链表
void Free_SSL(static_link link,int k);

//插入元素
bool insert(static_link link,int i,datatype num);

//删除元素
bool Delete(static_link link,int i );

//判断链表是否为空
bool isEmpty(static_link link);

//获取第i个对象的值
datatype getElement(static_link link,int i);


//历遍整个链表
void travel(static_link link);

#endif //STATIC_LINK_H



//********************static_link.c***********************
#include "static_link.h"


//初始化静态链表
bool InitList(static_link link)
{
	if(NULL == link)return false;
	for(int i = 0;i < MAXSIZE-1;i++)
	{
		link[i].curr = i+1;
	}
	link[MAXSIZE-1].curr = 0;
	return true;
}



//获取链表长度
size_t length(static_link link)
{
	if(NULL == link)return false;

	size_t index = link[MAXSIZE-1].curr;
	size_t count = 0;
	
	while(index)
	{
		count++;
		index = link[index].curr;
	}

	return count;
}

//Malloc_SLL若备用链表非空,则返回分配的节点下标,否则返回0
int Malloc_SLL(static_link link)
{
	if(0 == link[0].curr)return 0;

	int result = link[0].curr;
	link[0].curr = link[link[0].curr].curr;
	return result;
}

//Free_SSL将下标为K的空闲节点回收到备用链表
void Free_SSL(static_link link,int k)
{
	link[k].curr = link[0].curr;
	link[0].curr = k;
}

//插入元素
bool insert(static_link link,int i,datatype num)
{
	if(i<1 || i > length(link)+1)return false; //当输入的i小于1或者比链表长度+1大,则非法。
	int index = Malloc_SLL(link);

	if(index)
	{
		link[index].data = num;
		
		int index_front = MAXSIZE-1;
		for(int j = 1;j < i;j++)
		{
			index_front = link[index_front].curr;
		}
		link[index].curr = link[index_front].curr;
		link[index_front].curr = index;
		return true;
	}
	return false;
}

//删除元素
bool Delete(static_link link,int i )
{
	if(i<1 || i > length(link))return false;
	size_t index = MAXSIZE-1;
	for(int j =1;j < i;j++)
	{
		index = link[index].curr;
	}
	size_t tmp = link[index].curr;
	link[index].curr = link[tmp].curr;
	Free_SSL(link,i);
	return true;
}

//判断链表是否为空
bool isEmpty(static_link link)
{
	return !link[MAXSIZE-1].curr;
}

//获取第i个对象的值
datatype getElement(static_link link,int i)
{
	if(i<1 || i>length(link))return ~(1<<(sizeof(datatype)*8-1))+1;//这里由于函数的返回值是数据类型,因此不能返回false来报告输入错误,因此后面取了这个数据类型的最大值+1输出表示输入下标不合法

	size_t index = link[MAXSIZE-1].curr;
	for(size_t j = 1;j < i;j++)
	{
		index = link[index].curr;
	}
	return link[index].data;
}

//历遍整个链表
void travel(static_link link)
{
	size_t index = link[MAXSIZE-1].curr;
	while(index)
	{
		printf("%d ",link[index].data);
		index = link[index].curr;
	}
	printf("
");
}



//********************static_linkTest.c***********************
#include "static_link.h"





int main()

{

	Node arr[MAXSIZE];

	InitList(arr);

	

	printf("isEmpty: %d 
",isEmpty(arr));



	travel(arr);

	insert(arr,1,77);

	insert(arr,2,25);

	printf("isEmpty: %d 
",isEmpty(arr));

	travel(arr);

	//Delete(arr,2);

	//travel(arr);

	//printf("isEmpty: %d 
",isEmpty(arr));

	printf("arr[2]:%d 
",getElement(arr,2));

	printf("arr[3]:%d 
",getElement(arr,3));

	return 0;

}


3.循环链表
//******************************circular_link.h**************************************
#ifndef CIRCULAR_LINK_H
#define CIRCULAR_LINK_H

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef int datatype;

typedef struct circular_link
{
	datatype data;
	struct circular_link *next;
}Node,*Link;


//创建链表
Link create();

//获取链表长度
size_t length(Link link);

//获取第i-1个节点的地址,工具函数内部使用
Node *addressTool(Link link,size_t i);


//插入节点
bool insert(Link link,size_t i,datatype data);

//删除节点
bool Delete(Link link,size_t i);

//历遍节点
void travel(Link link);

//判断节点是否为空
bool isEmpty(Link link);

//获取第i个节点的数据
datatype getElement(Link link,size_t i);




#endif //CIRCULAR_LINK_H


//******************************circular_link.c**************************************
#include "circular_link.h"



//创建链表 创建失败返回NULL
Link create()
{
	Link link = (Link)malloc(sizeof(Node));
	link->next = link;
	return link;
}

//获取链表长度
size_t length(Link link)
{
	if(NULL==link || NULL==link->next)return false;


	Node *node = link->next;
	int count = 0;
	while(node != link)
	{
		count++;
		node = node->next;
	}

	return count;
}

//获取第i-1个节点的地址,工具函数内部使用
Node *addressTool(Link link,size_t i)
{
	Node *node = link;
	for(size_t j = 1;j < i;j++)
	{
		node = node->next;
	}
	return node;
}


//插入节点
bool insert(Link link,size_t i,datatype data)
{	
	if(i<1 || i > length(link)+1)return false;
	if(NULL == link)return false;

	Node *prev = addressTool(link,i);//获取第i-1个节点地址
	Node *curr = prev->next;//获取第i个节点地址
	
	Node *node = (Node *)malloc(sizeof(Node));//创建新节点	
	node->data = data;

	prev->next = node;
	node->next = curr;

	return true;
}

//删除节点
bool Delete(Link link,size_t i)
{
	if(i<1 || i>length(link))return false;
	if(NULL == link)return false;

	Node *prev = addressTool(link,i);
	Node *curr = prev->next;
	Node *temp = curr->next;

	prev->next = temp;
	free(curr);
	curr = NULL;
	return true;
}

//历遍节点
void travel(Link link)
{
	Node *node = link->next;
	while(node != link)
	{
		printf("%d ",node->data);
		node = node->next;
	}
	printf("
");
}

//判断节点是否为空
bool isEmpty(Link link)
{
	return link->next == link;
}

//获取第i个节点的数据
datatype getElement(Link link,size_t i)
{
	if(i<1 || i > length(link) || NULL == link)return !(1<<(sizeof(datatype)-1))+1;

	Node *node = link->next;

	for(size_t j = 1;j < i;j++)
	{
		node = node->next;
	}
	return node->data;
}


//******************************circular_linkTest.c**************************************

#include "circular_link.h"





int main()

{

	Link head = create();

	printf("isEmpty: %d 
",isEmpty(head));

	printf("%d 
",length(head));

	travel(head);



	insert(head,1,77);

	travel(head);

	printf("isEmpty: %d 
",isEmpty(head));

	insert(head,1,52);

	insert(head,1,44);

	travel(head);

	printf("%d 
",length(head));



	printf("head:1:%d 
",getElement(head,1));

	printf("head:2:%d 
",getElement(head,2));

	printf("head:3:%d 
",getElement(head,3));

	

//	Delete(head,1);

//	travel(head);

//	Delete(head,1);

//	travel(head);

//	Delete(head,1);

//	travel(head);

	return 0;

}

4.双向循环链表
//**********************************double_link.h************************************
#ifndef DOUBLE_LINK_H
#define DOUBLE_LINK_H

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef int datatype;

typedef struct double_link
{
	datatype data;
	struct double_link *prior;
	struct double_link *next;
}DulNode,*DulLink;


//创建链表
DulLink create();

//链表长度
size_t length(DulLink link);

//链表是否为空
bool isEmpty(DulLink link);

//获取第i-1和节点的地址,工具函数,内部使用
DulNode *addressTool(DulLink link,size_t i);

//插入节点
bool insert(DulLink link,size_t i,datatype data);

//删除节点
bool Delete(DulLink link,size_t i);

//历遍节点
void travel(DulLink link);


#endif //DOUBLE_LINK_H





//**********************************double_link.c************************************
#include "double_link.h"


//创建双向循环链表
DulLink create()
{
	DulLink link = (DulLink)malloc(sizeof(DulNode));
	link->prior = link;
	link->next  = link;
	return link;
}

//链表长度
size_t length(DulLink link)
{
	if(NULL == link)return 0;

	DulNode *node = link->next;
	size_t count = 0;
	while(node != link)
	{
		count++;
		node = node->next;
	}

	return count;
}

//链表是否为空
bool isEmpty(DulLink link)
{
	return (link->next == link);
}

//获取第i-1和节点的地址,工具函数,内部使用
DulNode *addressTool(DulLink link,size_t i)
{	
	DulNode *prev = link;
	for(int j = 1;j < i;j++)
	{
		prev = prev->next;
	}
	return prev;
}

//插入节点
bool insert(DulLink link,size_t i,datatype data)
{
	if(i<1 || i > length(link)+1)return false;
	if(NULL == link)return false;

	DulNode *prev = addressTool(link,i);//获得第i-1个节点的地址
	DulNode *old  = prev->next;//获得原来第i个地址

	DulNode *node = (DulNode *)malloc(sizeof(DulNode));//创建新节点
	node->data = data;

	prev->next = node;  //新节点与prev节点的连接
	node->prior= prev;

	node->next = old;
	old->prior = node;

	return true;
}

//删除节点
bool Delete(DulLink link,size_t i)
{
	if(i<1 || i>length(link))return false;
	if(NULL == link)return false;

	DulNode *prev = addressTool(link,i);//获取第i-1个节点地址
	DulNode *curr = prev->next;
	DulNode *behind = curr->next;

	prev->next = behind;//将第i-1个节点和i+1个节点连接起来
	behind->prior = prev;

	free(curr);//释放第i个节点
	curr = NULL;

	return true;
}

//历遍节点
void travel(DulLink link)
{
	DulNode *node = link->next;
	while(node != link)
	{
		printf("%d ",node->data);
		node = node->next;
	}
	printf("
");
}



//**********************************double_linkTest.c************************************
#include "double_link.h"


int main()
{
	DulLink head = create();
	printf("length: %d 
",length(head));
	printf("isEmpty: %d 
",isEmpty(head));

	insert(head,1,77);
	travel(head);
	insert(head,1,52);
	travel(head);
	insert(head,3,1314);
	travel(head);
	
	insert(head,1,74);
	insert(head,1,75);
	travel(head);
	Delete(head,2);
	travel(head);
	Delete(head,1);
	travel(head);
	return 0;
}

附件列表

原文地址:https://www.cnblogs.com/LyndonMario/p/9326332.html