不支持随机访问,因为不是连续的空间
链表的数据结构中一个存放元素 一个存放下一个元素的指针 头指针指向头结点 尾指针指向最后一个结点
#include<iostream>
using namespace std;
struct node
{
unsigned char elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned char elem);
void insert_node(int pos, unsigned char elem);
void delete_node(int pos);
void print_linklist(void);
int search(unsigned char elem);
int main()
{
create_list('a');
create_list('b');
create_list('c');
print_linklist();
insert_node(0, 'd');
print_linklist();
delete_node(0);
print_linklist();
return 0;
}
void create_list(unsigned char elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned char elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i<pos-1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(void)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem;
}
cout << endl;
}
int search(unsigned char elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
链表应用一:合并有序链表
其他的基础基本不变
思想:1.创建两个链表存储两组数据
2.再创建两个遍历指针比较大小
3.将比较大小后的数字放进一个新的链表中
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node*head);
int search(unsigned int elem);
int main()
{
node* head1 = nullptr;
node* head2 = nullptr;
create_list(1);
create_list(9);
create_list(13);
create_list(27);
head1 = head;
print_linklist(head1);
head = nullptr;
create_list(3);
create_list(5);
create_list(14);
create_list(81);
create_list(88);
create_list(95);
create_list(99);
head2 = head;
print_linklist(head2);
head = nullptr;
node* p1 = head1;
node* p2 = head2;
//任意数组为空的时候跳出循环
while (p1&&p2)
{
if (p1->elem <= p2->elem)
{
if (head == nullptr)
{
head = p1;
}
else
{
tail->next = p1;
}
tail = p1;
p1 = p1->next;
}
else
{
if (head == nullptr)
{
head = p2;
}
else
{
tail->next = p2;
}
tail = p2;
p2 = p2->next;
}
}
//p1为空时连接p2,否则连接p1
tail->next = p1 ? p1 : p2;
print_linklist(head);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i<pos-1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node*head)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem<<" ";
}
cout << endl;
}
int search(unsigned int elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
链表应用二:删除链表重复元素
输入范围0~9 10个数
1 2 1 4 5 4 ===》1 2 4 5
思考:如何标记已经出现的数字呢?
辅助数组,下标=要检索的内容 元素:状态(显示是否出现)
出现0 代表没有出现过 1代表出现过
100个数的话就100个大小(数组) 相当于下标对应数
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node*head);
int search(unsigned int elem);
void delete_repeat(node* head);
int main()
{
create_list(1);
create_list(2);
create_list(8);
create_list(2);
create_list(3);
create_list(9);
create_list(4);
create_list(6);
create_list(4);
create_list(8);
create_list(7);
create_list(5);
create_list(2);
create_list(9);
create_list(6);
print_linklist(head);
delete_repeat(head);
print_linklist(head);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i<pos-1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node*head)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem<<" ";
}
cout << endl;
}
int search(unsigned int elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
void delete_repeat(node* head)
{
int flag[10] = { 0 };
node* p = head;
node* q = nullptr;
flag[p->elem] = 1;
while (p->next!=nullptr)
{
if (flag[p->next->elem] == 0)
{
flag[p->next->elem] = 1;
p = p->next;
}
else
{
q = p->next;
p->next = q->next;
delete (q);
}
}
}
应用三:查找链表的中间节点
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node* head);
int search(unsigned int elem);
int find_mid(node* head);
int main()
{
create_list(1);
create_list(2);
create_list(3);
create_list(4);
create_list(5);
create_list(6);
create_list(7);
create_list(8);
create_list(9);
create_list(10);
print_linklist(head);
cout << find_mid(head);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node* head)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem << " ";
}
cout << endl;
}
int search(unsigned int elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
int find_mid(node* head)
{
node* p1 = head; //快指针
node* p2 = head;//慢指针
while (p1 != NULL && p1->next != NULL)//注意这块不能写反 否则会访问冲突
{
p1 = p1->next->next;
p2 = p2->next;
}
return p2->elem;
}
while (p1 != NULL && p1->next != NULL)//注意这块不能写反 否则会访问冲突
应用四:找到链表中倒数第n个结点的内容
思想:快慢指针
快指针总比慢指针多走n-1步
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node* head);
int search(unsigned int elem);
int find_last_nth(node* head,int n);
int main()
{
create_list(1);
create_list(2);
create_list(3);
create_list(4);
create_list(5);
create_list(6);
create_list(7);
create_list(8);
create_list(9);
create_list(10);
print_linklist(head);
cout << find_last_nth(head,5);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node* head)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem << " ";
}
cout << endl;
}
int search(unsigned int elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
int find_last_nth(node* head,int n)
{
node* p1 = head;//快指针
node* p2 = head;//慢指针
for (int i = 0; i < n - 1; i++)
{
p1 = p1->next;
}
while (p1->next!=NULL)
{
p1 = p1->next;
p2 = p2->next;
}
return p2->elem;
}
应用五:逆置单链表
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node* head);
int search(unsigned int elem);
void reverse_linklist(node* head);
int main()
{
create_list(1);
create_list(2);
create_list(3);
create_list(4);
create_list(5);
create_list(6);
create_list(7);
create_list(8);
create_list(9);
create_list(10);
print_linklist(head);
reverse_linklist(head);
print_linklist(head);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == NULL)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == NULL)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node* head)
{
node* p = NULL;
for (p = head; p != NULL; p = p->next)
{
cout << p->elem << " ";
}
cout << endl;
}
int search(unsigned int elem)
{
node* p;
for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}
return 0;
}
void reverse_linklist(node* head1)
{
node* n = NULL;
node* p = head1->next;
head1->next = NULL;
while (p->next!=NULL)
{
n = p->next;
p->next = head1;
head1 = p;
p = n;
}
p->next = head1;
head1 = p;
head = head1;
}
循环链表:
收尾相连
创建、插入、删除、查找都需要微改一点
#include<iostream>
using namespace std;
struct node
{
unsigned int elem;
node* next;
};
node* head = NULL;
node* tail = NULL;
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(node* head);
int search(unsigned int elem);
int main()
{
create_list(1);
create_list(2);
create_list(3);
create_list(4);
create_list(5);
create_list(6);
create_list(7);
create_list(8);
create_list(9);
create_list(10);
print_linklist(head);
return 0;
}
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
tail->next = p;
}
tail = p;
tail->next = head;
}
//插入分三种情况
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
node* p = new node;
int i = 0;
if (pos == 0) //插入第一个
{
p->elem = elem;
p->next = head;
head = p;
tail->next = head;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == head)//插入最后一个元素
{
tail = p;
}
}
}
//也是分三种情况
void delete_node(int pos)
{
node* pre = head;
node* p = NULL;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
tail->next = head;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == head)
{
tail = pre;
}
delete p;
}
}
void print_linklist(node* head)
{
node* p = head;
//这里不行因此想到用do先循环一次
/*for (p = head; p != head; p = p->next)
{
cout << p->elem << " ";
}*/
do
{
cout << p->elem << " ";
p = p->next;
} while (p!=head);
cout << endl;
}
int search(unsigned int elem)
{
node* p;
//用do
/*for (p = head; p; p = p->next)
{
if (p->elem == elem)
{
return 1;
}
}*/
do
{
p = head;
if (p->elem == elem)
{
return 1;
}
p = p->next;
} while (p!=head);
return 0;
}
循环列表应用一:经典笔试题,约瑟夫环
//头文件
#include<iostream>
using namespace std;
#pragma once
extern struct node* head;
extern struct node* tail;
struct node
{
unsigned int elem;
node* next;
};
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(void);
int search(unsigned int elem);
#include"linklist.h"
node* head=NULL;
node* tail=NULL;
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
if (head == NULL)
head = p;
else
tail->next = p;
tail = p;
tail->next = head;
}
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
int i = 0;
node* p = new node;
if (pos == 0) //插到最前面
{
p->elem = elem;
p->next = head;
head = p;
tail->next = head;
}
else
{
while (i < pos - 1)//其他情况
{
pre = pre->next;
i++;
}
p->elem = elem;
p->next = pre->next;
pre->next = p;
if (p->next == head) //插最后面
tail = p;
}
}
void delete_node(int pos)
{
node* pre = NULL, * p = NULL;
pre = head;
int i = 0;
if (pos == 0)
{
head = head->next;
delete pre;
tail->next = head;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next == head) //删除末尾
tail = pre;
delete p;
}
}
void print_linklist(void)
{
node* p = NULL;
p = head;
do
{
cout << p->elem<<" ";
p = p->next;
} while (p != head);
cout << endl;
}
int search(unsigned int elem)
{
node* p = NULL;
p = head;
do
{
if (p->elem == elem)
return 1;
p = p->next;
} while (p != head);
return 0;
}
#include<iostream>
using namespace std;
#include"linklist.h"
//循环列表
int main()
{
int n = 0, k = 0, m = 0;
int i = 0;
node* p = NULL, * q = NULL;
cout << "请输入人数" << endl;
cin >> n;
for (i = 1; i <= n; i++)
{
create_list(i);
}
print_linklist();
p = head;
cout << "请输入从第几人开始" << endl;
cin >> k;
while (--k)
p = p->next;
cout << "数到的报数人数m" << endl;
cin >> m;
if (1 == m)
{
for (i = 0; i < n; i++)
{
cout << p->elem;
p = p->next;
}
cout << endl;
}
else
{
while (n--)
{
for (i = 1; i < m - 1; i++)
p = p->next;
q = p;
p = p->next;
cout << p->elem;
q->next = p->next;
//delete p;
p = p->next;
}
cout << endl;
}
return 0;
}
双向链表:
//头文件
#include<iostream>
using namespace std;
#pragma once
extern struct node* head;
extern struct node* tail;
struct node
{
unsigned int elem;
node* next;
node* pre;
};
void create_list(unsigned int elem);
void insert_node(int pos, unsigned int elem);
void delete_node(int pos);
void print_linklist(void);
int search(unsigned int elem);
void reverse_print_linklist();//反转
//源文件
#include"linklist.h"
node* head=NULL;
node* tail=NULL;
void create_list(unsigned int elem)
{
node* p = new node;
p->elem = elem;
p->next = NULL;
p->pre = NULL;
if (head == NULL)
head = p;
else
{
tail->next = p;
p->pre = tail;
}
tail = p;
}
void insert_node(int pos, unsigned int elem)
{
node* pre = NULL;
pre = head;
int i = 0;
node* p = new node;
if (pos == 0) //插到最前面
{
p->elem = elem;
p->next = head;
head->pre = p;
p->pre = NULL;
head = p;
}
else
{
while (i < pos - 1)//其他情况
{
pre = pre->next;
i++;
}
p->elem = elem;
p->pre = pre;
p->next = pre->next;
if (p->next != NULL)
pre->next->pre = p;
pre->next = p;
if (p->next == NULL)
tail = p;
}
}
void delete_node(int pos)
{
node* pre = NULL, * p = NULL;
pre = head;
int i = 0;
if (pos == 0)
{
head = head->next;
head->pre = NULL;
delete pre;
}
else
{
while (i < pos - 1)
{
pre = pre->next;
i++;
}
p = pre->next;
pre->next = p->next;
if (p->next != NULL) //删除末尾
p->next->pre = pre;
else//if(p->next == NULL)
tail = pre;
delete p;
}
}
void print_linklist(void)
{
node* p = NULL;
p = head;
for (p; p; p = p->next)
cout << p->elem << " ";
cout << endl;
}
int search(unsigned int elem)
{
struct node* p;
for (p = head; p; p = p->next)
if (p->elem == elem)
return 1;
return 0;
}
void reverse_print_linklist()
{
struct node* p;
for (p = tail; p; p = p->pre)
cout << p->elem << " ";
cout << endl;
}
#include<iostream>
using namespace std;
#include"linklist.h"
//循环列表
int main()
{
create_list(1);
create_list(2);
create_list(3);
create_list(4);
create_list(5);
reverse_print_linklist();
return 0;
}