链表
struct Student { char name[20]; struct B // 上面有名字 底下没有 不占空间 结构体定义==数据类型 // 24字节 数据类型不占空间 { int a; }; int age; };
struct Student { char name[20]; struct // 上面没有名字 底下有 占空间 // 28字节 { int a; }B; int age; };
struct Student { char name[20]; struct B // 上面有名字 底下有 占空间 // 28字节 { int a; }B; int age; };
struct Student { char name[20]; struct // 上面没有名字 底下没有 占空间 // 28字节 { int a; }; int age; };
双向链表 为什么要有双向链表? 因为单链表有自身局限性(只能向后跑,不也能向前跑) 双向链表是啥? 和单链表相比,多了一个直接前驱指针
特殊情况(容易出错的点): 正常来说单链表需要处理2根线 而双向链表需要处理4根线 但是头插函数比较特殊,需要防止出现空链表导致少处理一根线 按位置删除函数也比较特殊,有可能删除的是最后一个节点 头删函数比较特殊 有可能只有一个有效节点需要删除
如果需要前驱 一般用于插入和删除操作等等 for(DNode *p=plist; p->next!=NULL; p=p->next); 如果不需要前驱 一般用于查找和打印 for(DNode *p=plist->next; p!=NULL; p=p->next);
dlist.h
#pragma once
typedef int ELEMTYPE;
typedef struct DNode
{
int data;
struct DNode* next;
struct DNode* prior;
}DNode,*PDNode;
void Init_dlist(PDNode plist);
bool Insert_head(PDNode plist, int val);
bool Insert_tail(PDNode plist, int val);
bool Insert_pos(PDNode plist, int pos, int val);
bool Del_head(PDNode plist);
bool Del_tail(PDNode plist);
bool Del_pos(PDNode plist, int pos);
bool Del_val(PDNode plist, int val);
struct DNode* Search(PDNode plist, int val);
PDNode Get_prior(PDNode plist, int val);
PDNode Get_next(PDNode plist, int val);
bool IsEmpty(PDNode plist);
dlist.cpp
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include"dlist.h"
void Init_dlist(PDNode plist)
{
assert(plist != NULL);
plist->next = NULL;
plist->prior =NULL;
}
bool Insert_head(PDNode plist, int val)
{
assert(plist != NULL);
DNode* pnewnode = (DNode*)malloc(sizeof(DNode) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
pnewnode->next = plist->next;
pnewnode->prior = plist;
if (plist->next != NULL)
{
plist->next->prior = pnewnode;
}
plist->next = pnewnode;
return true;
}
bool Insert_tail(PDNode plist, int val)
{
assert(plist != NULL);
DNode* pnewnode = (DNode*)malloc(sizeof(DNode) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
DNode* p = plist;
for (p; p->next != NULL; p = p->next);
pnewnode->next = p->next;
pnewnode->prior = p;
p->next = pnewnode;
return true;
}
bool Insert_pos(PDNode plist, int pos, int val)
{
assert(plist != NULL);
if (pos<0 || pos>Get_length(plist))
return false;
DNode* pnewnode = (DNode*)malloc(sizeof(DNode) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
DNode* p = plist;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
pnewnode->next = p->next;
pnewnode->prior = p;
if (p->next != NULL)
{
p->next->prior = pnewnode;
}
p->next = pnewnode;
return true;
}
bool Del_head(PDNode plist)
{
assert(plist != NULL && plist->next != NULL);
if (plist == NULL || plist->next == NULL)
return false;
DNode* p = plist->next;
if (p->next != NULL)
{
p->next->prior = plist;
}
plist->next = p->next;
free(p);
p = NULL;
return true;
}
bool Del_tail(PDNode plist)
{
assert(plist != NULL);
DNode* p = plist;
for (p; p->next != NULL; p = p->next);
p->prior->next = NULL;
free(p);
p = NULL;
return true;
}
bool Del_pos(PDNode plist, int pos)
{
assert(plist != NULL);
if (pos < 0 || pos >= Get_length(plist))
return false;
DNode* p = plist;
for (int i = 0; i <=pos; i++)
{
p = p->next;
}
if (p->next != NULL)
{
p->next->prior = p->prior;
}
p->prior->next = p->next;
free(p);
p = NULL;
return true;
}
bool Del_val(PDNode plist, int val)
{
assert(plist != NULL);
DNode* p = Search(plist, val);
if (p == NULL)
{
return false;
}
if (p->next != NULL)
{
p->next->prior = p->prior;
}
p->prior->next = p->next;
free(p);
p = NULL;
return true;
}
struct DNode *Search(PDNode plist, int val)
{
assert(plist != NULL);
DNode* p = plist->next;
for (p; p != NULL; p = p->next)
{
if (p->data == val)
{
return p;
}
}
return NULL;
}
PDNode Get_prior(PDNode plist, int val)
{
assert(plist != NULL);
DNode* p = Search(plist, val);
return p == NULL ? NULL : p->prior;
}
PDNode Get_next(PDNode plist, int val)
{
assert(plist != NULL);
DNode* p = Search(plist, val);
return p == NULL ? NULL : p->next;
}
bool IsEmpty(PDNode plist)
{
assert(plist != NULL);
return plist->next == NULL;
}
int Get_length(PDNode plist)
{
assert(plist != NULL);
int count = 0;
for (DNode* p = plist->next; p != NULL; p = p->next)
{
count++;
}
return count;
}
void Clear(PDNode plist)
{
Destroy(plist);
}
void Destroy(PDNode plist)
{
assert(plist != NULL);
while (plist->next != NULL)
{
DNode* p = plist->next;
plist->next = p->next;
free(p);
}
}
void Destroy2(PDNode plist)
{
assert(plist != NULL);
DNode* p = plist->next;
DNode* q = NULL;
plist->next = NULL;
while (p != NULL)
{
q = p->next;
free(p);
p = q;
}
}
void Show(PDNode plist)
{
for (DNode* p = plist->next; p != NULL; p = p->next)
{
printf("%d", p->data);
}
printf("\n");
}
循环链表
循环链表,将单链表中终端结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
clist.h
#pragma once
typedef int ELEM_TYPE;
typedef struct CNode
{
ELEM_TYPE data;
struct CNode* next;
}CNode, * PClist;
void Init_clist(PClist pl);
bool Insert_head(PClist pl, int val);
bool Insert_tail(PClist pl, int val);
bool Insert_pos(PClist pl, int pos, int val);
bool Del_head(PClist pl);
bool Del_tail(PClist pl);
bool Del_pos(PClist pl, int pos);
bool Del_val(PClist pl, int val);
struct CNode* Search(PClist pl, int val);
bool IsEmpty(PClist pl);
int Get_length(PClist pl);
void Show(PClist pl);
void Clear(PClist pl);
void Destroy(PClist pl);
void Destroy2(PClist pl);
PClist Get_prior(PClist pl, int val);
PClist Get_next(PClist pl, int val);
clist.cpp
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"clist.h"
void Init_clist(PClist pl)
{
assert(pl != NULL);
if (pl == NULL)
return;
pl->next = pl;
}
bool Insert_head(PClist pl, int val)
{
CNode* pnewnode = (CNode*)malloc(sizeof(CNode) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
pnewnode->next = pl->next;
pl->next = pnewnode;
return true;
}
bool Insert_tail(PClist pl, int val)
{
CNode* pnewnode = (CNode*)malloc(sizeof(CNode));
assert(pnewnode != NULL);
pnewnode->data = val;
CNode* p = pl;
for (p; p->next != pl; p = p->next);
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
bool Insert_pos(PClist pl, int pos, int val)
{
if (pos<0 || pos>Get_length(pl))
return false;
CNode* pnewnode = (CNode*)malloc(sizeof(CNode) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
CNode* p = pl;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
bool Del_head(PClist pl)
{
if (pl->next == pl)
return false;
CNode* p = pl->next;
pl->next = p->next;
free(p);
p = NULL;
return true;
}
bool Del_tail(PClist pl)
{
assert(pl != NULL && pl->next != pl);
if (pl == NULL || pl->next == pl)
{
return false;
}
CNode* p = pl;
for (p; p->next != pl; p = p->next)
{
if (p->next->next == pl)
{
break;
}
}
CNode* q = p->next;
p->next = q->next;
free(q);
q = NULL;
return true;
}
bool Del_pos(PClist pl, int pos)
{
if (pl == NULL || pos < 0 || pos >= Get_length(pl))
return false;
CNode* p = pl;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
CNode* q = p->next;
p->next = q->next;
free(q);
q = NULL;
return true;
}
bool Del_val(PClist pl, int val)
{
CNode* p = Get_prior(pl, val);
if (p == NULL)
{
return false;
}
CNode* q = p->next;
p->next = q->next;
free(q);
q = NULL;
return true;
}
struct CNode* Search(PClist pl, int val)
{
CNode* p = pl->next;
for (p; p != pl; p = p->next)
{
if (p->data == val)
{
return p;
}
}
return NULL;
}
bool IsEmpty(PClist pl)
{
return pl->next == pl;
}
int Get_length(PClist pl)
{
int count = 0;
for (CNode* p = pl->next; p != pl; p = p->next)
{
count++;
}
return count;
}
void Show(PClist pl)
{
for (CNode* p = pl->next; p != pl; p = p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
void Clear(PClist pl)
{
Destroy(pl);
}
void Destroy(PClist pl)
{
while (pl->next != pl)
{
CNode* p = pl->next;
pl->next = p->next;
free(p);
}
}
void Destroy2(PClist pl)
{
assert(pl != NULL && pl->next != pl);
CNode* p = pl->next;
CNode* q = NULL;
while (p != pl)
{
q = p->next;
free(p);
p = q;
}
pl->next = pl;
}
PClist Get_prior(PClist pl, int val)
{
CNode* p = pl;
for (p; p->next != pl; p = p->next)
{
if (p->next->data == val)
{
return p;
}
}
return NULL;
}
PClist Get_next(PClist pl, int val)
{
CNode* p = Search(pl, val);
return p == NULL ? NULL : p->next;
}
双向循环链表 双向循环链表和双向链表的区别: 1.最后一个节点的next指针不再指向NULL 而是指向头结点 2.头结点的prior指针不再指向NULL,而是指向尾结点
dclist.h
#pragma once
typedef int ELEM_TYPE;
typedef struct DCList
{
ELEM_TYPE data;
struct DCList* next;
struct DCList* prior;
}DCList, * PDClist;
void Init_dclist(PDClist pl);
bool Insert_head(PDClist pl, int val);
bool Insert_tail(PDClist pl, int val);
bool Insert_pos(PDClist pl, int pos, int val);
bool Del_head(PDClist pl);
bool Del_tail(PDClist pl);
bool Del_pos(PDClist pl, int pos);
bool Del_val(PDClist pl, int val);
PDClist Search(PDClist pl, int val);
bool IsEmpty(PDClist pl);
int Get_length(PDClist pl);
void Show(PDClist pl);
void Clear(PDClist pl);
void Destroy(PDClist pl);
void Destroy2(PDClist pl);
PDClist Get_prior(PDClist pl, int val);
PDClist Get_next(PDClist pl, int val);
dclist.cpp
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "dclist.h"
void Init_dclist(PDClist pl)
{
assert(pl != NULL);
if (NULL == pl)
return;
pl->next = pl;
pl->prior = pl;
}
DCList* BuyNode(int val)
{
DCList* pnewnode = (DCList*)malloc(sizeof(DCList) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
pnewnode->next = NULL;
pnewnode->prior = NULL;
return pnewnode;
}
bool Insert_head(PDClist pl, int val)
{
assert(pl != NULL);
if (pl == NULL)
return false;
DCList* pnewnode = BuyNode(val);
assert(pnewnode != NULL);
pnewnode->next = pl->next;
pnewnode->prior = pl;
if (pl->next != pl)
{
pl->next->prior = pnewnode;
}
pl->next = pnewnode;
if (pl->prior == pl)
{
pl->prior = pnewnode;
}
return true;
}
bool Insert_tail(PDClist pl, int val)
{
DCList* pnewnode = BuyNode(val);
assert(pnewnode != NULL);
DCList* p = pl;
for (pl; p->next != pl; p = p->next);
pnewnode->next = p->next;
pnewnode->prior = p;
p->next = pnewnode;
pl->prior = pnewnode;
return true;
}
bool Insert_pos(PDClist pl, int pos, int val)
{
DCList* pnewnode = BuyNode(val);
assert(pnewnode != NULL);
DCList* p = pl;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
pnewnode->next = p->next;
pnewnode->prior = p;
if (p->next != pl)
{
p->next->prior = pnewnode;
}
else
{
pl->prior = pnewnode;
}
p->next = pnewnode;
return true;
}
bool Del_head(PDClist pl)
{
assert(pl != NULL && pl->next != pl);
if (pl == NULL || pl->next == pl)
{
return false;
}
DCList* p = pl->next;
if (p->next == pl)
{
pl->next = pl->prior = pl;
free(p);
p = NULL;
}
else
{
pl->next = p->next;
p->next->prior = pl;
free(p);
p = NULL;
}
return true;
}
bool Del_tail(PDClist pl)
{
DCList* p = pl;
for (p; p->next != pl; p = p->next);
if (pl->next == p)
{
pl->next = pl;
pl->prior = pl;
}
else
{
p->prior->next = pl;
pl->prior = p->prior;
}
free(p);
p = NULL;
return true;
}
bool Del_pos(PDClist pl, int pos)
{
if (pos == 0)
return Del_head(pl);
if (pos == Get_length(pl) - 1)
return Del_tail(pl);
DCList* p = pl;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
DCList* q = p->next;
p->next = q->next;
q->next->prior = p;
free(q);
q = NULL;
return true;
}
bool Del_val(PDClist pl, int val)
{
DCList* p = Search(pl, val);
if (p == NULL)
{
return false;
}
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
p = NULL;
return true;
}
PDClist Search(PDClist pl, int val)
{
DCList* p = pl->next;
for (p; p != pl; p = p->next)
{
if (p->data == val)
{
return p;
}
}
return NULL;
}
bool IsEmpty(PDClist pl)
{
return pl->next == pl;
}
int Get_length(PDClist pl)
{
int count = 0;
DCList* p = pl->next;
for (p; p != pl; p = p->next)
{
count++;
}
return count;
}
void Show(PDClist pl)
{
DCList* p = pl->next;
for (p; p != pl; p = p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
void Clear(PDClist pl)
{
Destroy(pl);
}
void Destroy(PDClist pl)
{
while (pl->next != pl)
{
DCList* p = pl->next;
pl->next = p->next;
free(p);
p = NULL;
}
pl->prior = pl;
}
void Destroy2(PDClist pl)
{
DCList* p = pl->next;
DCList* q;
while (p != pl)
{
q = p->next;
free(p);
p = q;
}
pl->next = pl;
pl->prior = pl;
}
PDClist Get_prior(PDClist pl, int val)
{
DCList* p = Search(pl, val);
if (p == NULL)
{
return NULL;
}
return p->prior;
}
PDClist Get_next(PDClist pl, int val)
{
DCList* p = Search(pl, val);
if (p == NULL)
{
return NULL;
}
return p->next;
}
|