一、顺序表
1、顺序表概念
顺序存储的线性表
2、顺序表的初始化
(1)头文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
(2)管理顺序表的结构体
typedef struct
{
int capacity;//顺序表容量
int last;//最末元素下标
int *data;//顺序表,以整型数据为例
}sequenceList;
(3)顺序表的初始化
sequenceList * init_list(int cap)
{
sequenceList *list=malloc(sizeof(sequenceList));//给结构体本身分配空间
if(list != NULL)//如果成功
{
list->data=malloc(sizeof(int)*cap);//给顺序表分配空间
if(list -> data == NULL)//给顺序表分配空间失败,capacity和last就分配不了了,不用赋值了
{
free(list);//管理结构体没有意义,将管理结构体释放
return NULL;
}
//如果给顺序表分配空间成功就给剩下的两个结构体成员变量赋值
list -> capacity=cap;
list-> last=-1;
}
return list;
}
(4)main函数
int main()
{
sequenceList *list=init_list(10);//容量10
if(list==NULL)//判断初始化到底有没有成功,如果失败
{
printf("初始化顺序表失败\n");
exit(0);//退出程序
}
else
printf("初始化顺序表成功\n");
return 0;
}
3、顺序表的增删节点
3.1 顺序表的增添节点
bool isFULL(sequenceList *list)
{
return list->last==list->capacity-1;
}
//在顺序表表头插入一个新数据
bool insert(sequenceList *s,int data)
{
if(isFULL(s))
return false;
//将原有数据全部往后挪一位
for(int i=s->last;i>=0;i--)
s->data[i+1]=s->data[i];
//将新数据置入表头
s->data[0]=data;
s->last++;
return true;
}
3.2 顺序表的删除节点
//判断顺序表是否为空
bool isEmpty(sequenceList *list)
{
return list -> last==-1;
}
//查看当前顺序表的元素
void show(sequenceList *list)
{
if(isEmpty(list))
return;
for(int i=0;i<=list->last;i++)
printf("%d\t",list->data[i]);
printf("\n");
}
//将顺序表中指定的某个元素数据删除掉
bool removeNode(sequenceList *list,int data)
{
if(isEmpty(list))
return false;
//找到要删除的节点的位置
int i,pos=-1;
for(i=0;i<=list->last;i++)
{
if(list->data[i]==data)
{
pos=i;
break;
}
}
//找不到要删除的节点的位置
if(i>list->last)
return false;
return list;
//将所有数据全部往前挪一位
list->data[i]=list->data[i+1];
list->last--;
return true;
}
4 、顺序表的销毁
void destroy(sequenceList *list)
{
if(list==NULL)
return;
free(list->data);
free(list);
}
3.4 main函数
int main()
{
sequenceList *list=init_list(10);//容量10
if(list==NULL)//判断初始化到底有没有成功,如果失败
{
perror("初始化顺序表失败\n");
exit(0);//退出程序
}
else
printf("初始化顺序表成功\n");
int n;
while(1)
{
scanf("%d",&n);
if(n>0)
{
if(!insert(list,n))
{
printf("容量已满,插入失败\n");
continue;
}
}
else if(n<0)
{
if(!removeNode(list,-n))
{
printf("查无此数,删除失败!\n");
}
}
show(list);
}
destroy(list);
return 0;
}
二、链表
1、链表的概念
链式存储的线性表,简称链表。
2、链表的初始化
2.1 管理链表的结构体
typedef struct node
{
int data;
struct node *next;//指向下一个节点的指针
}node;
2.2 链表的初始化
2.2.21 单链表的初始化
node *initList()
{
node *head=malloc(sizeof(node));
if(head != NULL)
{
head->next=NULL;
}
return head;
}
2.2.2 单向循环链表的初始化
node *initList()
{
node *head=malloc(sizeof(node));
if(head != NULL)
{
head->next=head;
}
return head;
}
2.2.3 双向循环链表的初始化
typedef struct ListNode
{
int data; // 用于存储链表的值
struct ListNode *prev; // 指向当前链表节点前一个节点
struct ListNode *next; // 指向当前链表节点后一个节点
} ListNode;
ListNode *head = NULL;
ListNode *tail = NULL;
ListNode *init_list_node(int val)
{
ListNode *node = malloc(sizeof(ListNode));
if (node == NULL)
{ // malloc 申请内存空间失败
return NULL;
}
node->data = val;
node->prev = NULL;
node->next = NULL;
// 定义了在链表中的地位
head = node;
tail = node;
return node;
}
3、链表的增删节点
3.1 头插法
3.1.1 单链表
int addHeadBefore(int val)
{
// 创建一个新的节点
node *n = malloc(sizeof(node));
if (n == NULL)
{
return 0;
}
n->data = val;
// 让当前链表节点直线旧链表的头结点
n->next = head;
// 把head名头让给新的节点
head = n;
}
3.1.2 循环链表
//头插法
void insertHead(node *head,node *new)
{
new->prev=head;
new->next=head->next;
head ->next=new;
head->next->prev=new;
}
3.1.3 双向循环链表
ListNode *insertbefore(ListNode *n, int val)
{
// 创建新节点
ListNode *newNode = malloc(sizeof(ListNode));
newNode->data = val;
newNode->next = NULL;
newNode->prev = NULL;
ListNode *oldPrevNode = n->prev;
n->prev = newNode;
newNode->next = n;
if (oldPrevNode != NULL)
{
newNode->prev = oldPrevNode;
oldPrevNode->next = newNode;
}
else
{
head = newNode;
}
return newNode;
}
3.2 尾插法
3.2.1 单链表
int addTailAfter(int val)
{
// 创建一个新的节点
node *n = malloc(sizeof(node));
if (n == NULL)
{
return 0;
}
n->data = val;
n->next = NULL;
// 让当前链表最后一个节点指向 新节点
tail->next = n;
// 把tail名头让给新的节点
tail = n;
}
3.2.2 循环链表
//尾插法
void insertTail(node *head,node *new)
{
new->prev=head->prev;
new->next=head;
head->prev->next=new;
head->prev=new;
}
3.2.3 双向循环链表
4、链表的销毁
41 单链表
node *destory(node *head)
{
for(node *tmp=head,*n=tmp->next;tmp != NULL;tmp=n)
{
n=tmp->next;
free(tmp);
}
return NULL;
}
4.2 循环链表
node *destroy(node *head)
{
node *p;
for(p=head->next;p!=head;p=head->next)
{
removeNode(p);
free(p);
}
//释放头节点
free(head);
return NULL;
}
4.3 双向循环链表
// 销毁链表, 从头部开始销毁
int destoryByHead()
{
ListNode *n = head;
while (n != NULL)
{
// 先拿到下一个
head = n->next;
printf("%d \n", n->data);
free(n);
printf("free %d \n", n->data);
n = head;
}
head = NULL;
return 1;
}
// 销毁链表, 从尾部开始销毁
int destoryByTail()
{
ListNode *n = tail;
while (n != NULL)
{
// 先拿到上一个
tail = n->prev;
printf("%d \n", n->data);
free(n);
printf("free %d \n", n->data);
n = tail;
}
tail = NULL;
return 1;
}