目录
一、思维导图
二、作业
2.1 单向链表简单选择排序
/*
* function: 简单选择排序
* @param [ in]
* @param [out]
* @return
*/
void paixu(Linklist L)
{
//判断链表是否为空
//判断链表只有有一个节点
if( NULL==L || L->next==NULL )
{
return;
}
int i,j;
int len=Len_linklist(L);
Linklist p=L;
Linklist k=NULL;
for(i=0;i<len-1;i++)
{
Linklist q=p;
k=q;
for(j=i+1,p=L;j<len;j++,p=p->next)
{
if(q->data < p->data)
{
k=p;
}
}
if(k != q)
{
datatype t=k->data;k->data=q->data;q->data=t;
}
}
}
2.2 单向链表按元素插入
/*
* function: 按元素插入
* @param [ in]
* @param [out]
* @return
*/
Linklist insert_by_data(datatype key,datatype e,Linklist L)
{
int insert_pos=search_by_data(key,L);
if(insert_pos==-1)
return L;
L=insert_by_pos(insert_pos,e,L);
return L;
}
2.3 单向链表按元素修改
/*
* function: 按元素修改
* @param [ in]
* @param [out]
* @return
*/
Linklist modify_by_data(datatype key,datatype e,Linklist L)
{
int modify_pos=search_by_data(key,L);
if(modify_pos==-1)
return L;
L=modify_by_pos(modify_pos,e,L);
return L;
}
三、双链表
单向链表只可以向后遍历,使用起来不方便,那么引出双向链表,可以向前遍历。
3.1 双向链表结构体建立
typedef char datatype[20];
typedef struct Node
{
//数据域
datatype data;
//指针域:下一节点地址
struct Node *next;
//指针域:上一节点地址
struct Node *prev;
}*DouleLink;
3.2 双向链表节点创建
/*
* function: 申请节点
* @param [ in]
* @param [out]
* @return
*/
DouleLink create_node()
{
DouleLink node=(DouleLink)malloc(sizeof(struct Node));
if(NULL==node)
{
return NULL;
}
strcpy(node->data,"");
node->next=node->prev=NULL;
return node;
}
3.3 双向链表头插
/*
* function: 头插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_head(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
//
strcpy(s->data,e);
if(NULL!=L)
{
s->next=L;
L->prev=s;
}
L=s;
return L;
}
3.4 双向链表尾插
/*
* function: 尾插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_rear(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
strcpy(s->data,e);
//2.链表为空
if(NULL==L)
{
L=s;
return L;
}
//3.已有多个节点
//找到尾部节点
DouleLink rear=L;
while(rear->next!=NULL)
{
rear=rear->next;
}
rear->next=s;
s->prev=rear;
return L;
}
3.5 双向链表头删
/*
* function: 头删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_head(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink q=L->next;
strcpy(L->data,q->data);
L->next=q->next;
if(q->next!=NULL)
q->next->prev=L;
free(q);
q=NULL;
return L;
}
3.6 双向链表尾删
/*
* function: 头删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_head(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink q=L->next;
strcpy(L->data,q->data);
L->next=q->next;
if(q->next!=NULL)
q->next->prev=L;
free(q);
q=NULL;
return L;
}
3.7 双向链表遍历
/*
* function: 循环输出
* @param [ in]
* @param [out]
* @return
*/
void output(DouleLink L)
{
//1.如果为空
if(NULL==L)
{
return;
}
//2.如果存在节点
//正向遍历
puts("正向遍历:");
while(L->next!=NULL)
{
printf("%s\t",L->data);
L=L->next;
}
printf("%s\n",L->data);
//逆向遍历
puts("逆向遍历:");
while(L!=NULL)
{
printf("%s\t",L->data);
L=L->prev;
}
puts("");
}
3.8 双链表全部代码
double_head.h
#ifndef __HEAD__H__
#define __HEAD__H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char datatype[20];
typedef struct Node
{
//数据域
datatype data;
//指针域:下一节点地址
struct Node *next;
//指针域:上一节点地址
struct Node *prev;
}*DouleLink;
DouleLink insert_head(datatype e,DouleLink L);
void output(DouleLink L);
DouleLink insert_rear(datatype e,DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_rear(DouleLink L);
#endif
double_main.c
#include "double_head.h"
int main(int argc, const char *argv[])
{
DouleLink L=NULL;
int n;
datatype e;
printf("please enter n:");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
printf("please enter e:");
scanf("%s",e);
// L=insert_head(e,L);
L=insert_rear(e,L);
}
//循环输出
output(L);
//头删
L=delete_head(L);
printf("头删后:\n");
output(L);
puts("");
//尾删
L=delete_rear(L);
printf("尾删后:\n");
output(L);
puts("");
return 0;
}
double_test.c
#include "double_head.h"
/*
* function: 申请节点
* @param [ in]
* @param [out]
* @return
*/
DouleLink create_node()
{
DouleLink node=(DouleLink)malloc(sizeof(struct Node));
if(NULL==node)
{
return NULL;
}
strcpy(node->data,"");
node->next=node->prev=NULL;
return node;
}
/*
* function: 头插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_head(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
//
strcpy(s->data,e);
if(NULL!=L)
{
s->next=L;
L->prev=s;
}
L=s;
return L;
}
/*
* function: 循环输出
* @param [ in]
* @param [out]
* @return
*/
void output(DouleLink L)
{
//1.如果为空
if(NULL==L)
{
return;
}
//2.如果存在节点
//正向遍历
puts("正向遍历:");
while(L->next!=NULL)
{
printf("%s\t",L->data);
L=L->next;
}
printf("%s\n",L->data);
//逆向遍历
puts("逆向遍历:");
while(L!=NULL)
{
printf("%s\t",L->data);
L=L->prev;
}
puts("");
}
/*
* function: 尾插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_rear(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
strcpy(s->data,e);
//2.链表为空
if(NULL==L)
{
L=s;
return L;
}
//3.已有多个节点
//找到尾部节点
DouleLink rear=L;
while(rear->next!=NULL)
{
rear=rear->next;
}
rear->next=s;
s->prev=rear;
return L;
}
/*
* function: 头删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_head(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink q=L->next;
strcpy(L->data,q->data);
L->next=q->next;
if(q->next!=NULL)
q->next->prev=L;
free(q);
q=NULL;
return L;
}
/*
* function: 尾删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_rear(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink rear=L;
while(rear->next!=NULL)
rear=rear->next;
rear->prev->next=NULL;
free(rear);
rear=NULL;
return L;
}
四、双向循环链表
因为双向链表在找尾节点是,需要从第一个节点遍历到最后一个节点,时间复杂度高,而且单链表只能向后遍历,不可以向前,所以引出双向循环链表。双向循环链表最大特点是:不需要通过循环找到尾节点,相对方便。
4.1 双向循环链表结构体建立
typedef char datatype[20];
typedef struct Node
{
//数据域
datatype data;
//指针域
struct Node *next;
//指针域
struct Node *prev;
}*DouleLink;
4.2 双向循环链表节点创建
/*
* function: 申请节点
* @param [ in]
* @param [out]
* @return
*/
DouleLink create_node()
{
DouleLink node=(DouleLink)malloc(sizeof(struct Node));
if(NULL==node)
{
return NULL;
}
strcpy(node->data,"");
node->next=node->prev=NULL;
return node;
}
4.3 双向循环链表头插
/*
* function: 头插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_head(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
//
strcpy(s->data,e);
if(NULL!=L)
{
s->next=L;
L->prev=s;
}
L=s;
return L;
}
4.4 双向循环链表尾插
/*
* function: 尾插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_rear(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
strcpy(s->data,e);
//2.链表为空
if(NULL==L)
{
L=s;
return L;
}
//3.已有多个节点
//找到尾部节点
DouleLink rear=L;
while(rear->next!=NULL)
{
rear=rear->next;
}
rear->next=s;
s->prev=rear;
return L;
}
4.5 双向循环链表头删
/*
* function: 头删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_head(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink q=L->next;
strcpy(L->data,q->data);
L->next=q->next;
if(q->next!=NULL)
q->next->prev=L;
free(q);
q=NULL;
return L;
}
4.6 双向循环链表尾删
/*
* function: 尾删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_rear(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink rear=L;
while(rear->next!=NULL)
rear=rear->next;
rear->prev->next=NULL;
free(rear);
rear=NULL;
return L;
}
4.7 双向循环链表遍历
/*
* function: 循环输出
* @param [ in]
* @param [out]
* @return
*/
void output(DouleLink L)
{
//1.如果为空
if(NULL==L)
{
return;
}
//2.如果存在节点
//正向遍历
puts("正向遍历:");
while(L->next!=NULL)
{
printf("%s\t",L->data);
L=L->next;
}
printf("%s\n",L->data);
//逆向遍历
puts("逆向遍历:");
while(L!=NULL)
{
printf("%s\t",L->data);
L=L->prev;
}
puts("");
}
4.8 双向循环链表所有代码
head.h
#ifndef __HEAD__H__
#define __HEAD__H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char datatype[20];
typedef struct Node
{
//数据域
datatype data;
//指针域
struct Node *next;
//指针域
struct Node *prev;
}*DouleLink;
DouleLink insert_head(datatype e,DouleLink L);
void output(DouleLink L);
DouleLink insert_rear(datatype e,DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_head(DouleLink L);
DouleLink delete_rear(DouleLink L);
#endif
main.c
#include "double_head.h"
int main(int argc, const char *argv[])
{
DouleLink L=NULL;
int n;
datatype e;
printf("please enter n:");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
printf("please enter e:");
scanf("%s",e);
// L=insert_head(e,L);
L=insert_rear(e,L);
}
//循环输出
output(L);
//头删
L=delete_head(L);
printf("头删后:\n");
output(L);
puts("");
//尾删
L=delete_rear(L);
printf("尾删后:\n");
output(L);
puts("");
return 0;
}
test.c
#include "double_head.h"
/*
* function: 申请节点
* @param [ in]
* @param [out]
* @return
*/
DouleLink create_node()
{
DouleLink node=(DouleLink)malloc(sizeof(struct Node));
if(NULL==node)
{
return NULL;
}
strcpy(node->data,"");
node->next=node->prev=NULL;
return node;
}
/*
* function: 头插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_head(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
//
strcpy(s->data,e);
if(NULL!=L)
{
s->next=L;
L->prev=s;
}
L=s;
return L;
}
/*
* function: 循环输出
* @param [ in]
* @param [out]
* @return
*/
void output(DouleLink L)
{
//1.如果为空
if(NULL==L)
{
return;
}
//2.如果存在节点
//正向遍历
puts("正向遍历:");
while(L->next!=NULL)
{
printf("%s\t",L->data);
L=L->next;
}
printf("%s\n",L->data);
//逆向遍历
puts("逆向遍历:");
while(L!=NULL)
{
printf("%s\t",L->data);
L=L->prev;
}
puts("");
}
/*
* function: 尾插
* @param [ in]
* @param [out]
* @return
*/
DouleLink insert_rear(datatype e,DouleLink L)
{
//1.创建新节点
DouleLink s=create_node();
if(NULL==s)
return L;
strcpy(s->data,e);
//2.链表为空
if(NULL==L)
{
L=s;
return L;
}
//3.已有多个节点
//找到尾部节点
DouleLink rear=L;
while(rear->next!=NULL)
{
rear=rear->next;
}
rear->next=s;
s->prev=rear;
return L;
}
/*
* function: 头删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_head(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink q=L->next;
strcpy(L->data,q->data);
L->next=q->next;
if(q->next!=NULL)
q->next->prev=L;
free(q);
q=NULL;
return L;
}
/*
* function: 尾删
* @param [ in]
* @param [out]
* @return
*/
DouleLink delete_rear(DouleLink L)
{
//1.如果链表为空
if(NULL==L)
return L;
//2.判断链表只有一个节点
if(NULL==L->next)
{
free(L);
L=NULL;
return L;
}
//3.有多个节点
DouleLink rear=L;
while(rear->next!=NULL)
rear=rear->next;
rear->prev->next=NULL;
free(rear);
rear=NULL;
return L;
}