1.双链表
只要求掌握思想就可以了,完整代码不必深究。
这里是图解
上面已经给出关键代码,下面的代码可能实现的有些粗糙,但还是和单链表一样的逻辑,自己不要太陷入细节。
//双链表的创立和基本的操作
//不带头节点
#include<iostream>
using namespace std;
typedef struct link
{
struct link* prior;//直接前驱的指针
int data;
struct link* next;//直接后继的指针
}*Linklist;
int findnode(Linklist head, int e);
void freenode(Linklist& head);
//初始化数据,这里为了表示简单一点就不带头节点,head=NULL判空
//这里用return的方式,不用引用了
Linklist create(Linklist head) {
head = (Linklist)malloc(sizeof(link));//初始画头节点
head->data = 1;
head->next = NULL;
head->prior = NULL;
link*temp = head;//创建临时指针
for (int i = 2; i < 6; i++) {
link* body = (link*)malloc(sizeof(link));
body->next = NULL;
body->data = i;
body->prior = temp;//连前驱
temp->next = body;//将前面的next指向新建的
temp = temp->next;//temp更新
}
return head;
}
//打印函数
void printList(Linklist head) {
link* current = head;
while (current) {
std::cout << current->data << " -> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
}
//释放链表
void freenode(Linklist& head) {
Linklist temp = head;
while (temp)
{
head = head->next;
free(temp);
temp = head;
}
}
// insert data
Linklist insertlink(Linklist head, int e, int add) {
Linklist temp = head;//临时变量
Linklist newnode = (Linklist)malloc(sizeof(link));
newnode->data = e;
newnode->next = NULL;
newnode->prior = NULL;
if (add == 1) { //1. insert in head node
newnode->next = head;
head->prior = temp;
head = temp;
}
else {
//find where position insert in
for (int i = 1; i < add - 1; i++) {//find insert's position 's last position
temp = temp->next;
if (!temp)//find the final node but node is not exist
{
cout << "false" << endl;
return head;
}
}
if (temp && temp->next == NULL) {//2. insert in the final position
temp->next = newnode;
newnode->prior = temp;
}
else {//3. insert in the middle position
newnode->next = temp->next;
temp->next->prior = newnode;
temp->next = newnode;
newnode->prior = temp;
}
}
return head;
}
//delete data
Linklist deletelink(Linklist head, int e) {
Linklist temp = head;
while (temp) {
if (temp->data == e) {//1.delete first node
if (temp->prior == NULL) {
head = temp->next;
if (head) { head->prior = NULL; }
temp->next = NULL;
freenode(temp);
return head;
}
if (temp->next && temp->prior) {//2.delete middle node
temp->prior->next = temp->next;
temp->next->prior = temp->prior;
temp->next = NULL;
temp->prior = NULL;
freenode(temp);
return head;
}
if (temp->next == NULL)//3.delete last node
{
temp->prior->next = NULL;
temp->prior = NULL;
freenode(temp);
return head;
}
}
temp = temp->next;
}
cout << "delete false" << endl;
return head;//false
}
//按值查找find node
int findnode(Linklist head, int e) {
Linklist temp = head;
int i = 1;
while (temp) {
if (temp->data == e) {
return i;
}
i++;
temp = temp->next;
}
return -1;
}
//update node
void updatenode(Linklist head, int oldnode, int newnode)
{
int find = 0;
Linklist temp = head;
while (temp) {
if (temp->data == oldnode) {
find = 1;
break;
}
temp = temp->next;
}
if (find == 1) {
temp->data = newnode;
cout << "update ok " << endl;
}
else {
cout << "update false" << endl;
}
}
void test01() {
Linklist head = NULL;
head = create(head);
cout << "创建好的链表为" << endl;
printList(head);
cout << endl;
cout << "在第三个位置添加一个数字8" << endl;
head = insertlink(head, 8, 3);
printList(head);
cout << endl;
cout << "将元素4删除" << endl;
head = deletelink(head, 4);
printList(head);
cout << endl;
//display(head);
cout << "元素3的位置为" << findnode(head, 3)<<endl<<endl;
cout << "将数字5变为数字9" << endl;
updatenode(head, 5, 9);
printList(head);
cout << endl;
free(head);
}
int main() {
test01();
system("pause");
return 0;
}
2.循环链表
实现约瑟夫环
//循环链表----实现约瑟夫
#include<iostream>
using namespace std;
typedef struct node {
int num;
struct node* next;
}*linklist;
//初始化循环链表
//这里的实现不带头节点
linklist initlist(linklist head) {
head = (linklist)malloc(sizeof(node));
head->num = 1;
head->next = NULL;
linklist temp = head;
for (int i = 2; i <= 8; i++) {
linklist body = (linklist)malloc(sizeof(node));
body->num = i;
body->next = NULL;
temp->next = body;
temp = temp->next;
}
temp->next = head;
return head;
}
//约瑟夫环
void findwin(linklist head, int k, int m)//k代表报数的位置,m代表报到m出列
{
linklist temp = head;
//find num of k,temp是位置的节点
while (temp->num != k) {
temp = temp->next;
}
//prenode是k位置的上一个节点
//find winner
linklist prenode = NULL;
while (temp->next != temp) {
for (int i = 1; i < m; i++) {
prenode = temp;找到出列的人前面一个节点
temp = temp->next;
}
//删除
prenode->next = temp->next;
cout << "出列的人的编号为" << temp->num << endl;
//free(temp);
temp = prenode->next;
}
cout << "出列的人的编号为" << temp->num << endl;
//free(temp);
}
void test01() {
int n = 0, k = 0, m = 0;
linklist head = NULL;
cout << "输入圆桌上的人数:" << endl;
cin >> n;
head = initlist(head);
cout << "从第几个人开始报数" << endl;
cin >> k;
cout << "数到几的人出列:" << endl;
cin >> m;
findwin(head, k, m);
}
int main() {
test01();
system("pause");
return 0;
}
静态链表
静态链表的设计初衷是为了在数组环境中模拟链表的一些特性,特别是链表在插入和删除操作上的高效性(不需要移动大量元素),同时尽可能地利用数组的空间连续性和随机访问的优点。
//静态链表
//静态链表不仅能快速地找到数据又能够快速地添加和删除数据
//静态链表使用数组模拟链表
#include<iostream>
using namespace std;
#define maxsize 10
typedef struct arraylist {
int data;
int cur;
}*arraylink;
void link1(arraylink array);
int mallocsapce(arraylink array);
int initarray(arraylink array);
//创建备用链表
void link1(arraylink array)
{
int i = 0;
for (i = 0; i < maxsize - 1; i++) {
array[i].cur = i + 1;
array[i].data = 0;
}
array[maxsize - 1].cur = 0;
array[maxsize - 1].data = 0;
}
//提取空闲空间
int mallocsapce(arraylink array) {
int a = array[0].cur;//保存空闲节点
if (array[0].cur) {
array[0].cur = array[a].cur;//第一个节点指向分配的节点下一位节点,如果是最后一位节点那么则第一个节点的cur为0
}
return a;
}
int initarray(arraylink array) {
link1(array);
//创建首元节点
int first = mallocsapce(array);
array[first].data = 1;
array[first].cur = 0;
int temp = first;//temp作为数组“指针”指向链表最后一个
for (int i = 2; i < 6; i++) {
int j = mallocsapce(array);//创建新节点
array[j].data = i;//初始化新节点
array[temp].cur = j;//将新节点连接到链表中
temp = j;//temp仍然指向最后一个
}
array[temp].cur = 0;//新链表的cur为0
return first;//因为初始化相当于都是基于first节点而来的,所以要返回first
}
void display(arraylink array, int first) {//要用到这两个参数
int tempBody = first;//tempBody准备做遍历使用
while (array[tempBody].cur) {//假设只有三个数据节点,那么在tempBody=3时显然cur为0,循环结束
printf("%d,%d\n", array[tempBody].data, array[tempBody].cur);
tempBody = array[tempBody].cur;
}
printf("%d,%d\n", array[tempBody].data, array[tempBody].cur);
}
void test01() {
arraylist array[maxsize];
int first = initarray(array);
display(array, first);
}
int main() {
test01();
system("pause");
return 0;
}
顺序表和链表对比