08.数据结构学习2.0
1、链表
1、链表的构成:
节点:数据+指向下一个节点的指针
#define ElementType int
struct Node
{
ElementType data;//存放数据
struct Node* next;//指向下一节点的指针,里面存放的是地址
};
struct LinkList
{
struct Node *head;//定义头节点
int len;//记录链表长度
};
2、特点:插入和删除比较方便,不利于随机存放
3、链表的初始化:
int InitLinList(struct LinkList *list)
{
//给头节点申请空间
list->head = (struct Node *)malloc(sizeof(struct Node));
if(list->head == NULL)
{
printf("InitLinkList malloc Error!\n");
return false;
}
list->head->data = 0;
list->head->next = NULL;
return true;
}
4、链表的操作:
(1)、封装一个函数实现创建新节点
struct Node* CreateNode(ElementType element)
{
//给一个新节点申请空间
struct Node *NewNode = (struct Node *)malloc(sizeof(struct Node));
if(NewNode == NULL)//判断申请节点是否成功
{
printf("CreateNode malloc error!\n");//申请失败,则打印错误信息,返回;
return NULL;
}
NewNode->data = element;//给新节点指向的数据赋值
NewNode->next = NULL;//next指向空
return NewNode;
}
(2)、释放链表所有节点
void FreeLinkList(struct LinkList *list)
{
struct Node *TravelPoint = list->head->next;//申请一个节点指向头节点
while(TravelPoint != NULL)//当头结点的下一节点不为空,一直释放一个往后挪一个
{
free(list->head);//释放头节点
list->head = TravelPoint;//让头节点指向原来的下一个
TravelPoint = list->head->next;//头节点的下一个节点也更新
}
free(list->head);//最后剩下一个头节点给他释放
list->head = NULL;//头节点指向空
list->len =0;//长度为0
}
(3)、遍历输出链表
void Travel(struct Node* list)
{
struct Node *TravelPoint = list->head->next;//设置一个遍历指针指向头指针的下一个节点
while(TravelPoint != NULL)//当下一个不为空的时候
{
printf("%d ",TravelPoint->data);//输出内容
TravelPoint = TravelPoint->next;//指针指向下一个
}
printf("\n");
}
(4)、增加链表
【1】、尾插法
void InsertTail(struct LinkList *list,ElementType element)
{
//创建一个新节点里面存要插入的值
struct Node *NewNode = CreateNode(element);
if(NewNode == NULL)//判断新节点是否申请成功
{
printf("InsertTail CreateNode Error!\n");//失败打印错误信息,返回;
return ;
}
struct Node * TravelPoint = list->head;//设置一个遍历指针指向头节点
while(TravelPoint->next != NULL)//判断当前节点是否已经是最后一个节点
{
TravelPoint = TravelPoint->next;//不是,则向后移,直到找到最后一个节点
}
TravelPoint->next = NewNode;//将最后一个节点指向新节点
list->len++;//长度加一
}
【2】、头插法
void InsertHead(struct LinkList *list,ElementType element)
{
//创建一个新节点里面存要插入的值
struct Node *NewNode = CreateNode(element);
if(NewNode == NULL)//判断新节点是否申请成功
{
printf("InsertTail CreateNode Error!\n");//失败打印错误信息,返回;
return ;
}
NewNode->next = list->head->next;//新节点指向头节点的下一个节点
list->head->next = NewNode;//头节点指向新节点
list->len++;//长度加一
}
【3】、按位序插入
void InsertIndex(struct LinkList *list,ElementType element,int index)
{
if(index < 0 || index > list->len)//判断插入数据位置是否合法
{
printf("InsertIndex illegal place!\n");//不合法打印错误信息,返回;
return ;
}
struct Node *NewNode = CreateNode(element);//申请创建新节点
if(NewNode == NULL)//判断申请新节点是否成功
{
printf("InsertIndex CreateNode Error!\n");//申请失败,打印错误信息返回;
return;
}
struct Node *TravelPoint = list->head;//申请一个遍历指针指向head
while(index != 0)//找到要插入的位置,index从0开始数
{
TravelPoint = TravelPoint->next;//向后挪直到找到该位置
index--;
}
NewNode->next = TravelPoint->next;
TravelPoint->next = NewNode;
list->len++;
}
(5)、删除节点
【1】、按位序删除
void RemoveByIndex(struct LinkList *list,int index)
{
if(index < 0 || index >= list->len)//判断插入数据位置是否合法
{
printf("RemoveByIndex illegal place!\n");//不合法打印错误信息,返回;
return ;
}
struct Node *TravelPoint = list->head;//申请一个遍历指针指向head
while(index != 0)//找到要插入的位置,index从0开始数
{
TravelPoint = TravelPoint->next;//向后挪直到找到该位置
index--;
}
struct Node *FreeNode = TravelPoint->next;//设置要删除的节点
TravelPoint->next = FreeNode->next;
free(FreeNode);//释放要删除的节点
list->len--;//长度减一
}
【2】、按值删除
void RemoveByElement(struct LinkList *list,ElementType element)
{
//设置一个遍历指针进行比较对比
struct Node* TravelPoint = list->head;
while(TravelPoint->next != NULL)//判断节点的下一节点是否为空
{
if(TravelPoint->next->data == element)//判断是否为我们要找的值
{
struct Node *FreeNode = TravelPoint->next;//设置一个节点存放我们要删除的节点
TravelPoint->next = FreeNode->next;//当前节点的后继指向下一节点的后继节点
free(FreeNode);//释放要删除的节点
list->len--;//长度减一
}
else
{
TravelPoint = TravelPoint->next;//如果当前节点的判断结束,则进入下一个节点判断
}
}
}
(6)、查找
【1】、按位查找
//int型返回值是没有办法去判断值是否是有有效值的,只有空指针才能表示返回值是否有效
ElementType *FindByIndex(struct LinkList *list, ElementType element, int index)
{
if(index < 0 || index >= list->len)
{
printf("FindByIndex illegal place!\n");
return NULL;
}
struct Node* TravelPoint = list->head;
while(index != 0)
{
TravelPoint = TravelPoint->next;
index--;
}
return &TravelPoint->next->data;
}
【2】、按值查找
int *FindByElement(struct LinkList *list,ElementType element)
{
//申请一个数组存放下对应找到的值的数组下标
int *findVector = (int *)malloc(sizeof(int)*(list->len+1));
if(findVector == NULL)//判断申请是否失败
{
printf("FindByElement malloc error!\n");//打印错误信息,返回NULL
return NULL;
}
struct Node* TravelPoint = list->head;//从设置一个标志头节点开始,头节点没有数据所以判断从下一节点开始
int count=0,k=0;//设置计数器
while(TravelPoint->next!=NULL)//当下一个节点不为空的时候进入循环
{
if(TravelPoint->next->data == element)//判断下一节点的值是否等于要查找的值
{
findVector[k] = count;//存储当前下标
k++;//新数组的下标加一
}
count++;//原数组的下标移动
TravelPoint = TravelPoint->next;//进入下一个值的判断
}
findVector[k] = -1;//设置新数组的最后一位为标志位
return findVector;
}
(7)、修改节点的值
【1】、按位置修改
void SetValuebyIndex(struct LinkList *list, ElementType element, int index)
{
if (index < 0 || index >= list->len)
{
printf("SetValueByIndex illegal place!\n");
return;
}
struct Node *TravelPoint = list->head;
while (index != 0)
{
TravelPoint = TravelPoint->next;
index--;
}
TravelPoint->next->data = element;
}
【3】、按值修改
void SetValueByElement(struct LinkList *list, ElementType oldValue, ElementType newValue)
{
int *findVector = FindByElement(list,oldValue);
if(findVector == NULL)
{
printf("Can't find any elements!\n");
return ;
}
int *temp = findVerctor;
while(*temp != -1)
{
SetValueByIndex(list,newValue,*temp);
temp++;
}
free(findVerctor);
}
(8)、冒泡排序
void BubbleSort(struct LinkList *list)
{
for(int i=0;i<list->len;i++)//记录当前扫描的次数
{
struct Node *TravelPoint = list->head;//设置一个遍历指针
for(int j=0;j<list->len-i-1;j++)//开始扫描交换
{
//判断两个节点值的大小,小则交换
if(TravelPoint->next->data < TravelPoint->next->next->data)
{
struct Node *Prev = TravelPoint->next;
struct Node *Next = TravelPoint->next->next;
Prev->next = Next->next;
Next->next = Prev;
TravelPoint->next = Next;
}
TravelPoint =TravelPoint->next;
}
}
}
(9)、逆序输出
【1】、非递归
void Reserve(struct LinkList *list)
{
struct Node *prev = NULL;
struct Node *cur = list->head->next;
struct Node *Next = cur->next;
while(Next != NULL)
{
cur->next = prev;
prev = cur;
cur = Next;
Next = cur->next;
}
cur->next = prev;
list->head->next = cur;
}
【2】、递归
struct Node *Reserve2(struct Node *node)
{
struct Node * tail;
if(node->next!=NULL)
{
tail = Reserve2(node->next);
node->next->next = node;
node->next = NULL;
return tail;
}
return node;
}
(10)、合并链表
struct LinkList *Mergelist(struct LinkList *list1,struct LinkList *list1)
{
BubbleSort(list1);
BubbleSort(list2);
struct LinkList* list3 = (struct LinkList *)malloc(sizeof(struct LinkList));
if(list3 == NULL)
{
printf("MergeList malloc error!\n");
return NULL;
}
InitLinkList(list3);
list3->len = list1->len + list2->len;
struct Node * TravelPoint = list3->head;
list1->head=list1->head->next;
list2->head=list2->head->next;
while(list1->head != NULL && list2->head != NULL)
{
if(list1->head->data < list2->head->data)
{
TravelPoint->next = list1->head;
list1->head = list1->head->next;
}
else
{
TravelPoint->next = list2->head;
list2->head = list2->head->next;
}
TravelPoint = TravelPoint->next;
}
if(list1->head != NULL)
{
TravelPoint->next = list1->head;
}
if(list2->head != NULL)
{
TravelPoint->next = list2->head;
}
return list3;
}