链表
每个数据节点除了保存数据以外,还至少有一个指针域存储下一个节点的地址
单链表
每个数据节点有一个数据域一个指针域 只能从前向后检索
- 每个元素都是一个对象,每一个对象有一个关键字 val 和一个指针 next(对象中还可以有其它的辅助数据 / 卫星数据);
- x 为链表的一个元素,x.next 指向它的后继元素;如果 x.next = NIL,则元素 x 没有后继元素,是链表的最后一个元素(即链表的尾 / tail);
- 属性 L.head 指向链表的第一个元素,如果 L.head = NIL ,则链表为空。
程序中的两种逆置方法图解:
1.头插法逆置
// 单链表的逆置--头插法逆置
void ReverseList1(LinkList list)
{
LinkList p = list->next;
LinkList q = p;//避免list->next是空链表
list->next = NULL;
while(p!=NULL)
{
q=p->next;
p->next = list->next;
list->next=p;
p = q;
}
}
list->next = NULL;
q=p->next;
在后面头插入节点的时候用的是先把后面连在一起再连接前面的方法:
list->next=p;
p = q;
2.第二种倒置方法多加了一个参数k 与第一种差不多
void ReverseList2(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
list->next=q;
}
完整程序
main.cpp
#include <stdio.h>
#include "LinkList.h"
int main()
{
LNode head;
Init_List(&head);
for (int i = 0; i < 4; ++i)
{
Insert_ListTail(&head, i + 10);
}
Show(&head);
Insert_ListHead(&head, 100);
Show(&head);
Insert_ListPos(&head, 200, 1);
Show(&head);
Insert_ListPos(&head, 300, 3);
Show(&head);
Insert_ListTail(&head, 400);
Show(&head);
Delete_ListHead(&head);
Show(&head);
Delete_ListTail(&head);
Show(&head);
Delete_ListPos(&head, 4);
Show(&head);
return 0;
}
LinkList.cpp
#include "LinkList.h"
#include <assert.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
//
static LinkList ApplyLNode(ElemType val, LinkList next)
{
LinkList s = (LinkList)malloc(sizeof(LNode));
assert(s != NULL);
if (s == NULL)
{
return NULL;
}
s->data = val;
s->next = next;
return s;
}
static LinkList ApplyLNode2()
{
LinkList s = (LinkList)malloc(sizeof(LNode));
assert(s != NULL);
if (s == NULL)
{
return NULL;
}
return s;
}
static int Length(LinkList list)
{
LinkList p = list->next;
int count = 0;
while (p != NULL)
{
count++;
p = p->next;
}
return count;
}
/
bool Init_List(LinkList list)
{
assert(list != NULL);
if (list == NULL)
{
return false;
}
list->next = NULL;
return true;
}
// 1、申请一个结点用于存储数据
// 2、将结点插入到指定的位置:
// 1)将新结点的指针域指向原始结点的指针域
// 2)将原始结点的指针域指向新节点
bool Insert_ListHead2(LinkList list, ElemType val)
{
LinkList s = ApplyLNode2(); // 1
if (s == NULL) return false;
s->data = val;
s->next = list->next; // 2.1
list->next = s; // 2.2
return true;
}
bool Insert_ListHead(LinkList list, ElemType val)
{
LinkList s = ApplyLNode(val, list->next);
if (s == NULL) return false;
list->next = s;
return true;
}
bool Insert_ListTail(LinkList list, ElemType val)
{
LinkList p = list;
while (p->next != NULL) p = p->next;
return Insert_ListHead(p, val);
}
bool Insert_ListPos(LinkList list, ElemType val, int pos)
{
if (pos <= 0 || pos > Length(list) + 1) return false;
LinkList p = list;
for (; pos > 1; --pos) p = p->next;
return Insert_ListHead(p, val);
}
void Show(LinkList list)
{
LinkList p = list->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
bool Delete_ListHead(LinkList list)
{
return Delete_ListPos(list, 1);
}
bool Delete_ListTail(LinkList list)
{
return Delete_ListPos(list, Length(list));
}
bool Delete_ListPos(LinkList list, int pos)
{
if (pos <= 0 || pos > Length(list)) return false;
LinkList p = list;
for (; pos > 1; --pos) p = p->next;
LinkList q = p->next;
p->next = q->next;
free(q);
return true;
}
// 单链表的逆置--头插法逆置
void ReverseList1(LinkList list)
{
LinkList p = list->next;
LinkList q = p;//避免list->next是空链表
list->next = NULL;
while(p!=NULL)
{
q=p->next;
p->next = list->next;
list->next=p;
p = q;
}
}
void ReverseList2(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
list->next=q;
}
void ReverseList3(LinkList list)
{
LinkList p = list->next;
LinkList q = NULL,k=NULL;
while(p!=NULL)
{
k=p->next;
p->next = q;
q = p;
p = k;
}
}
void Clear(LinkList list)
{
while(Length(list))
{
Delete_ListHead(list);
}
}
LinkList.h
#pragma once
typedef int ElemType;
typedef struct _Node
{
ElemType data;
struct _Node *next;
}LNode, *LinkList;
bool Init_List(LinkList list);
bool Insert_ListHead(LinkList list, ElemType val);
bool Insert_ListHead2(LinkList list, ElemType val);
bool Insert_ListTail(LinkList list, ElemType val);
bool Insert_ListPos(LinkList list, ElemType val, int pos);
void Show(LinkList list);
bool Delete_ListHead(LinkList list);
bool Delete_ListTail(LinkList list);
bool Delete_ListPos(LinkList list, int pos);
// 单链表逆置
void ReverseList(LinkList list);