1. 静态链表
#include<iostream>
using namespace std;
struct Node
{
int num; //数据域
struct Node *next; //指针域 该指针指向结构体类型
};
int main()
{
//创建三个结点
struct Node Node1 = { 1, NULL };
struct Node Node2 = { 2, NULL };
struct Node Node3 = { 3, NULL };
//建立三个结点之间的联系
Node1.next = &Node2;
Node2.next = &Node3;
//遍历打印
struct Node *cur = &Node1; //定义一个当前指针指向第一个结点
while (cur)
{
cout << cur->num<<" ";
cur = cur->next;
}
system("pause");
}
以上创建节点并建立联系的两部分可以合并成一个部分,代码如下:
//构建节点的同时,建立了联系
Node Node3 = { 3, NULL };
Node Node2 = { 2, &Node3 }; //注意取地址符
Node Node1 = { 1, &Node2 };
//创建头节点
Node *headNode = &Node1; //头节点只需要首节点的地址即可,无需数据
//访问链表数据
//创建一个移动的指针
Node *cur = headNode;
while (cur)
{
printf("%d\n", cur->num);
cur = cur->next;
}
2. 动态链表
链表中的对象,一般都是动态创建的。
比如,当用户需要添加一个对象时,从控制台输入信息,如何创建一个对象,插入到链表。
那么对象从哪儿来??
从malloc或者new开始
C语言
c语言中采用malloc,动态创建的对象生命期,自malloc之时生效,到free之后失效。
// 代码说明
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;//以上只是单个结点的创建,并没有实现构造每个结点之间的联系 //如何创建联系?? //通过以下步骤:
// 1. 构造结点类型
(要明白什么时候用数组/结构体,数组:类型相同的数据;结构体:类型不同的数据)
struct Node
{
数据域;
指针域;
}
// 2.创建表头
struct Node* createList()
// 3. 创建结点
struct Node* createNode(int data)
// 4. 构造联系
void insertListByHead(struct Node* headNode, int data)
{
struct Node* newNode = createNode(data); // 参数data只是int类型,通过createNode(data)将其转换成结点类型
}
C语言代码实现
#include<stdlib.h>
#include<stdio.h>
//动态链表 堆区
struct Node
{
int data;
struct Node* next;
};
//创建一个表头(不存储数据) 结构体变量
struct Node* createList()
{
//表头
struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
//变量 初始化头节点
headNode->next = NULL;
return headNode;
}
//创建节点(存储数据,用户传入) 结构体变量
struct Node* createNode(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
//变量 初始化每个节点(将传入的每个数据转换成节点)
newNode->data = data;
newNode->next = NULL;
return newNode;
}
//头插法(指定头节点为headNode的链表)
void insertListByHead(struct Node* headNode, int data)
{
//将传入的data转换成节点
struct Node* newNode = createNode(data);
newNode->next = headNode->next;
headNode->next = newNode;
}
//尾插法
void insertListByTail(struct Node* headNode, int data)
{
struct Node* newNode = createNode(data);
struct Node* cur = headNode;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = newNode;
newNode->next = NULL;
}
//指定位置插入
void insertListByAppoin(struct Node* headNode, int data, int pos)
{
struct Node* newNode = createNode(data);
//定义两个指针,一个cur指针,指向第一个节点;一个pre指针,指向头节点
struct Node* cur = headNode->next;
struct Node * pre = headNode;
int count = 1;
while (cur != NULL && count < pos )
{
count += 1;
pre = cur;
cur = cur->next;
}
/* //1. 针对传入的posData参数 > 链表节点个数,程序会把它当作“未找到指定位置”
if (cur == NULL)
{
printf("未找到指定位置");
return;
}
else
{
newNode->next = cur;
pre->next = newNode;
}
*/
//2. 如果传入的posData参数 > 链表节点个数,程序会把它当作尾插法
newNode->next = cur;
pre->next = newNode;
}
//头删法
void deleteListByHead(struct Node* headNode)
{
//如果只有一个头节点,无法删除
if (headNode->next == NULL)
{
printf("无法删除");
return;
}
struct Node* cur = headNode->next;
headNode->next = cur->next;
}
//尾删法
void deleteListByTail(struct Node* headNode)
{
//如果只有一个头节点,无法删除
if (headNode->next == NULL)
{
printf("无法删除");
return;
}
struct Node* cur = headNode->next;
struct Node* pre = headNode;
if (cur->next!= NULL)
{
pre = cur;
cur = cur->next;
}
pre->next = NULL;
}
//指定位置删除
void deleteListByAppoin(struct Node* headNode, int pos)
{
//如果只有一个头节点,无法删除
if (headNode->next == NULL || pos < 1)
{
printf("无法删除");
return;
}
int count = 1;
struct Node* cur = headNode->next;
struct Node* pre = headNode;
while (count < pos)
{
count += 1;
pre = cur;
cur = cur->next;
}
//传入的参数pos越界,超出链表长度
if (cur == NULL)
{
printf("无法找到指定位置\n");
return;
}
else
{
pre->next = cur->next;
}
}
//遍历打印节点(指定以headNode头节点开始的链表)
void printList(struct Node* headNode)
{
struct Node* cur = headNode->next; //当前指针指向下一个节点
while (cur)
{
cout << cur->data << endl;
cur = cur->next;
}
}
int main()
{
struct Node* list = createList(); //创建链表,返回表头
insertListByHead(list,1);
insertListByHead(list,2);
insertListByHead(list,3);
insertListByTail(list,4);
printList(list);
deleteListByAppoin(list, 1);
insertListByAppoin(list, 999, 4);
printList(list);
system("pause");
}
其它问题
访问成员时,什么时候用“->”, 什么时候用“.”???
指针类型用“->”,普通变量用“.”。
例子如下:
struct node
{
int a;
struct node* next;
};
int main()
{
//结构体普通变量,访问成员用“."
struct node bianliang1, bianliang2;
bianliang1.a = 10;
bianliang1.next = &bianliang2; //注意加地址符
cout << bianliang1.a << endl;
//结构体指针变量,访问成员用“->"
//定义的指针指向上一个变量
struct node *p1 = &bianliang1, *p2 = &bianliang2;
//(*p1).next = p2; 不采用这种方式,麻烦
p1->a = 20;
p1->next = p2;
cout << bianliang1.a << endl; //内容通过指针被修改
cout << p1->a << endl;
system("pause");
}
结果
3.单链表的一些算法
1)实现从尾到头打印单链表(递归)
void nixuprint(struct Node* headNode) //传入链表,链表的构建见上面的代码
{
if (headNode == NULL || headNode->pnext == NULL)
{
return;
}
Node *nextNode = headNode->pnext;
//cout << nextNode->num << endl; //顺序打印
nixuprint(nextNode);
cout << nextNode->num << endl; //逆序打印
}
未完待续。。。