目录
1 从尾到头打印链表
1.1 初始化结点
结点包括数据域和指针
typedef struct Link{
int elem;
struct Link *next;
}link;
1.2 创建一个链表
定义一个头结点作为链表表头,注意头结点数据域为空
link *createlink()
{
link *newlink =(link *)malloc(sizeof(link));
newlink->next = NULL;
return newlink;
}
1.3 创建一个节点
因为后序需要做插入节点函数,有了节点才能插入,因此这里需要写一个创建节点的函数,与创建链表非常相似,只是创建节点需要输入对应数据域的数值。
//创造一个节点//
link *createnode(int data)
{
link *newnode = (link *)malloc(sizeof(link));
newnode->elem =data;
newnode->next = NULL;
return newnode;
}
1.4 插入一个节点
插入节点分为头插法和尾插法,下面第一个代码表示头插法,及在头结点后面插入新节点,其后节点依次后移,最新插入的元素在链表的最前面。函数参数选择:插入到那个链表,插入的数据。
//插入结点,参数:插入哪个链表,插入结点的数值是多少?头插法
void add_node(link *headNode,int data)
{
link *newnode = createnode(data);
//头插法
newnode->next = headNode->next;
headNode->next = newnode;
}
尾插法
//插入结点,参数:插入哪个链表,插入结点的数值是多少?
void add_nodetotail(link *headNode,int data)
{
link *tail;
link *newnode = createnode(data);
tail = headNode;
while(tail->next != 0)
{
tail=tail->next;
}
tail->next = newnode;
newnode->next= NULL;
}
1.5 打印含头结点的链表
由于预打印的列表包含头结点即首元结点是第二个节点。
void displayLink(link *headNode)
{
link *pMove = headNode->next;
while(pMove)
{
printf("%d",pMove->elem);
pMove = pMove->next;
}
printf("\n");
}
1.6 删除一个指定数值的节点
需要定义两个结构体指针分别用于存储链表的遍历以及存储前目标指针的前一个节点。
void deletelem(link *headNode,int data)
{
int pos = 0;
link *temp = headNode;
link *front;
while(temp->elem != data)//这里跳出while的节点temp就是删除的节点
{
front = temp;//front是要删除节点的前一个节点
temp = temp->next;
}
front->next = temp->next;//将欲删除节点的前一个节点的next指向删除节点的next,保证链表的完整
free(temp);//释放data所在的节点
}
1.7 完整代码
初始化一个链表为1234然后倒序打印,采用先遍历链表然后将数值采用头插法添加到新链表上,在打印新链表实现
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
int elem;
struct Link *next;
}link;
//初始化链表函数
link *initLink()
{
int i;
link *p = NULL;
link *temp = (link*)malloc(sizeof(link));
p = temp;
temp->elem =1;
temp->next =NULL;
for(i=2;i<5;i++)
{
link *a = (link *)malloc(sizeof(link));
a->elem = i;
a->next = NULL;
temp->next = a;
temp = a;
}
return p;
}
link *InitLink()
{
int i;
link *p = (link *)malloc(sizeof(link));
link *temp = p;
for(i = 1; i < 5; i++)
{
link *a = (link *)malloc(sizeof(link));
a->elem = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
link *createlink()
{
link *newlink =(link *)malloc(sizeof(link));
newlink->next = NULL;
return newlink;
}
//创造一个节点//
link *createnode(int data)
{
link *newnode = (link *)malloc(sizeof(link));
newnode->elem =data;
newnode->next = NULL;
return newnode;
}
//插入结点,参数:插入哪个链表,插入结点的数值是多少?头插法
void add_node(link *headNode,int data)
{
link *newnode = createnode(data);
//头插法
newnode->next = headNode->next;
headNode->next = newnode;
}
void displayLink(link *headNode)
{
link *pMove = headNode->next;
while(pMove)
{
printf("%d",pMove->elem);
pMove = pMove->next;
}
printf("\n");
}
void print_tail_to_head(link *p)
{
link *pp,*qq;
qq = p->next;
link *new = createlink();
while(qq)
{
add_node(new,qq->elem);
printf("%d",qq->elem);
qq = qq->next;
}
printf("\n");
displayLink(new);
}
void deletelem(link *headNode,int data)
{
int pos = 0;
link *temp = headNode;
link *front;
while(temp->elem != data)//找到data所在的节点
{
front = temp;
temp = temp->next;
}
front->next = temp->next;
free(temp);//释放data所在的节点
}
int main()
{
link *p = InitLink();
print_tail_to_head(p);
return 0;
}
打印结果
1234
4321
2 创建链式队列
2.1 初始化函数(节点、链表、创建一个新节点)
结点包括数据域和指针
typedef struct Link{
int elem;
struct Link *next;
}link;
link *createlink()
{
link *newlink =(link *)malloc(sizeof(link));
newlink->next = NULL;
return newlink;
}
//创造一个节点//
link *createnode(int data)
{
link *newnode = (link *)malloc(sizeof(link));
newnode->elem =data;
newnode->next = NULL;
return newnode;
}
2.2 链式队列从链表尾部插入数据
link *Queue_tail_write(link *tail,int data)
{
link *new_elem = (link *)malloc(sizeof(link));
new_elem->elem = data;
new_elem->next = NULL;
tail->next = new_elem;
tail =new_elem;
return tail;
}
2.3 链式队列从链表头读出数据
link *Queue_top_read(link *top,link *tail)
{
if(top->next==NULL)
{
printf("链表为空,读取识别");
return tail;
}
link *temp = top->next;
printf("出队元素为%d\n",temp->elem);
top->next = temp->next;
if(temp == tail)//这里如果不判断tail,把tail所指向的节点释放了,tail会变成野指针。
{
tail = top;
printf("队列为空\n");
}
free(temp);
return top;
}
2.4 完整代码
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
int elem;
struct Link *next;
}link;
link *createlink()
{
link *newlink =(link *)malloc(sizeof(link));
newlink->next = NULL;
return newlink;
}
//链式队列尾部插入数据
link *Queue_tail_write(link *tail,int data)
{
link *new_elem = (link *)malloc(sizeof(link));
new_elem->elem = data;
new_elem->next = NULL;
tail->next = new_elem;
tail =new_elem;
return tail;
}
//链式队列出队读取队首数据
link *Queue_top_read(link *top,link *tail)
{
if(top->next==NULL)
{
printf("链表为空,读取识别");
return tail;
}
link *temp = top->next;
printf("出队元素为%d\n",temp->elem);
top->next = temp->next;
if(temp == tail)
{
tail = top;
printf("队列为空\n");
}
free(temp);
return top;
}
int main()
{
link *top,*tail;
top = tail = createlink();
tail = Queue_tail_write(tail,1);
tail = Queue_tail_write(tail,2);
tail = Queue_top_read(top,tail);
tail = Queue_top_read(top,tail);
tail = Queue_top_read(top,tail);
return 0;
}
3 创建链式队列
队列的特点是先进先出,队尾出队,队首入队。链式队列和单向链表的建立相同都需要建立头结点(使队列元素的入队出队步骤相同),头指针始终指向头结点,第一个含有数据的节点在头结点后一个元素。
#include <stdio.h>
#include <stdlib.h>
typedef struct QNode
{
int data;
struct QNode *next;
}Q_Node;
typedef struct Queue{
Q_Node *front;
Q_Node *reat;
}QueueLink;
//新建一个空队列
QueueLink *Queue_LinkInit(QueueLink *q)
{
Q_Node *node = (Q_Node *)malloc(sizeof(Q_Node));
node->next = NULL;
q->front = q->reat = node;//给q->front和q->reat分配内存
return q;
}
//入队 入那个队列 数据是多少
QueueLink *enter_q(QueueLink *queue,int data)
{
Q_Node *elem = (Q_Node *)malloc(sizeof(Q_Node));
if(!elem)
{
printf("节点内存分配异常");
}
else
{
elem->data = data;
elem->next = NULL;
queue->reat->next = elem;//queue->reat指向队列最后一个元素
queue->reat = elem;
}
return queue;
}
//出队 从哪个队列出队
QueueLink *out_q(QueueLink *queue)
{
Q_Node *elem = queue->front->next;
if(queue->front == queue->reat)
{
printf("队列为空");
}
else
{
printf("%d\n",elem->data);
queue->front->next = elem->next;
if(queue->reat == elem)
{
printf("已经全部出队");
queue->reat = queue->front;
}
free(elem);
}
return queue;
}
Printhead_node(QueueLink *queue)
{
if(queue->front == queue->reat)
{
printf("队列为空");
}
else
{
Q_Node *elem = queue->front->next;
while(elem)
{
printf("%d\n",elem->data);
elem = elem->next;
}
}
}
主函数分别采用结构体变量以及结构体指针的方式定义,注意区别,采用结构体变量由于编译时直接分配内存,因此可以直接给newLink.front和newLink.reat赋值为NULL;但是对比下面定义成结构体指针的newLink1不能直接给newLink1->front和newLink1->reat赋值,需要先给结构体指针分配内存(与结构体变量的内存大小一致),举一反三:如果结构体指针指向的结构体的成员中仍存在结构体指针,若想对此指针指向的变量赋值,需要分别给两个指针分配内存。
int main()
{
QueueLink newLink;
newLink.front = newLink.reat = NULL;
Queue_LinkInit(&newLink);
enter_q(&newLink,1);
out_q(&newLink);
//或者
QueueLink *newLink1 = (QueueLink *)malloc(sizeof(QueueLink));//这里定义的结构体指针没有有效的内存地址,需要分配空间
newLink1->front = newLink1->reat = NULL;
Queue_LinkInit(newLink1);//这里目的在于给 newLink1->front和 newLink1->reat指针分配内存,因为要给newLink1->front->data赋值
enter_q(newLink1,1);
out_q(newLink1);
return 0;
}
运行结果: