排序插入节点
设民航公司有一个自动预订飞机票的系统,该系统中有一张用双重链表示的乘客表,表中节点按乘客姓氏的字母序相连
为该系统写一个当任意乘客订票时修改乘客表的算法
算法思想
av是可用数组空间的最小下标
typedef struct Node
{
char data[maxsize];
int prev, next;
}unode;
void Insert(unode user[max], int av)
{
// 读入字符串s,是乘客的姓名
scanf("%s", s);
// 将字符串s的内容拷贝到新的节点的数据域
strcopy(user[av].data, s);
// 创建工作指针cur
cur = 1;
if (strcmp(user[cur].data, s) < 0)
{
// 沿右链查找
while (cur && strcmp(user[cur].data, s) < 0)
{
unode prev = cur;
cur = user[cur].next;
}
user[av].next = cur;
user[av].prev = prev;
// 将新节点链入表中
user[prev].next = av;
user[cur].prev = av;
}
else
{
while (cur && strcmp(user[cur].data ,s) > 0)
{
unode prev = cur;
cur = user[cur].next;
}
user[av].next = prev;
user[av].prev = cur;
// 将新节点链入表中
user[prev].prev = av;
user[prev].next = av;
}
}
按数据类型拆分链表
已知L为没有头节点的单链表中第一个节点的指针,每个节点数据域存放一个字符,该字符可能是英文字母字符或数字字符或其他字符
构造三个以带头节点的单循环链表表示的线性表,是每个表中只含有同一类字符
算法思想
首先要构造含有这三类字符的表头节点
然后从原链表的第一个节点开始,根据数据域的类型分别插入到三个链表之一
采用前插法
void OneToThree(LinkList &L, &l1, &l2, &l3)
{
l1 = (LinkList)malloc(sizeof(LNode));
l2 = (LinkList)malloc(sizeof(LNode));
l3 = (LinkList)malloc(sizeof(LNode));
l1->next = l1, l2->next = l2, l3->next = l3;
LNode* cur = L, *next;
while (cur)
{
next = cur->next;
if (cur->data >= 'a' && cur->data <= 'z' || cur->data >= 'A' && cur->data <= 'Z')
{
cur->next = l1->next;
l1->next = cur;
}
else if (cur->data >= '0' && cur->data <= '9')
{
cur->next = l2->next;
l2->next = cur;
}
else
{
cur->next = l3->next;
l3->next = cur;
}
cur = next;
}
}
输出次数最多的前k个词
设键盘输入n个英语单词,输入格式为n,w1,w2,…wn,其中n表示随后输入英语单词的个数
建立一个单向链表,实现
- 如果单词重复出现,只在链表中保留一个
- 有一个计数域,记录该单词重复的次数,然后输出出现次数最多的前k个单词
算法思想
用字符数组表示英文单词,判断单词是否相等,使用strcmp函数
typedef struct Node
{
// 频度域
int freq;
char word[maxsize];
struct Node* next;
}LNode, *LinkList;
LinkList Create()
{
LinkList L;
// 申请头节点
L = (LinkList)malloc(sizeof(LNode));
// 链表初始化
L->next = NULL;
// 建立n个节点的链表
for (i = 1; i <= n; i++)
{
scamf("%s", s);
// cur是工作指针,prev是前驱指针
LNode* cur = L->next;
LNode* prev;
while (cur)
{
if (strcmp(cur->data, s) == 0)
{
cur->freq++;
break;
}
else
{
// 指针后移
prev = cur;
cur = cur->next;
}
}
// 该词没出现过,插入链表
if (cur == NULL)
{
cur = (LinkList)malloc(sizeof(LNode));
strcopy(cur->data, s);
cur->freq = 1;
cur->next = NULL;
prev->next = cur;
}
}
return L;
}
void CreatOut()
{
LinkList L;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
for (i = 1; i <= n; i++)
{
scanf("%s", s);
LNode* cur = L->next;
LNode* prev = cur;
while (cur)
{
if (strcmp(cur->data, s) == 0)
{
// 重复出现,频度+1
cur->freq++;
prev->next = cur->next;
prev = L;
LNode* cur2 = L->next;
while (cur2->freq > cur->freq)
{
prev = cur2;
cur2 = cur2->next;
}
prev->next = cur;
cur->next = cur2;
}
else
{
prev = cur;
cur = cur->next;
}
}
if (cur == NULL)
{
cur = (LinkList)malloc(sizeof(LNode));
strcopy(cur->data, s);
cur->freq = 1;
cur->next = NULL;
prev->next = cur;
}
}
int k, i = 0;
scanf("输入要输出单词的个数%d", &k);
cur = L->next;
// 输出频度最高的k个单词
while (cur && i < k)
{
printf("第%3d个单词%s出现%3d次\n", ++i, cur->data, cur->freq);
cur = cur->next;
}
}
三个链表公共元素
已知三个带头节点的线性链表A、B和C,节点均从小到大非递减次序排列
对A表,使A链表仅留下三个表中均包含的数据元素的节点,且没有值相同的节点,并释放所有无用的节点
m,n,p表示链表长度
算法思想
首先查找A和B的公共数据,再去C中找有无该数据,要消除重复元素,要保存前驱
LinkList Common(LinkList &A, &B, &C)
{
LNode* cur1 = A->next, *cur2 = B->next, *cur3 = C->next;
// prev是A表中当前节点的前驱指针
LNode* prev = A;
// ABC均不为空时,查找共同元素
while (cur1 && cur2 && cur3)
{
while (cur1 && cur2)
{
// A表的值小于B表,删去这个节点
if (cur1->data < cur2->data)
{
LNode* del = cur1;
cur1 = cur1->next;
free(del);
}
// A表的值大于B表,B表指针后移
else if (cur1->data > cur2->data)
{
cur2 = cur2->next;
}
else if (cur1 && cur2)
{
// 判断C表,当C表指针的数据小于A表,C表后移
while (cur3 && cur3->data < cur1->data)
{
cur3 = cur3->next;
}
if (cur3)
{
// C表数据大于A表,删除A表节点
if (cur3->data > cur1->data)
{
LNode* del = cur1;
cur1 = cur1->next;
free(del);
}
// 值相等
else
{
// 如果cur1是第一个节点
if (prev == A)
{
prev->next = cur1;
prev = cur1;
cur1 = cur1->next;
}
// 如果是重复节点,不链入A表
else if (prev->data == cur1->data)
{
LNode* del = cur1;
cur1 = cur1->next;
free(del);
}
else
{
prev->next = cur1;
prev = cur1;
cur1 = cur1->next;
}
}
}
// 链表的工作指针后移
cur2 = cur2->next;
cur3 = cur3->next;
}
}
}
// A表到尾,尾置空
if (cur1 == NULL)
prev->next = NULL;
// A表未到尾,删除剩余元素
else
{
prev->next = NULL;
while (cur1)
{
LNode* del = cur1;
cur1 = cur1->next;
free(del);
}
}
}
两个整数数位求和
给定两个用链表表示的整数,每个节点表示一个数位,这些数位是反向存放的,也就是个位排在链表首部
对这两个整数求和,用链表形式返回结果
算法思想
设置carry为当前递归的进位信号,
如果两个链表均不为空。则以L1为根节点,更新其值,并让该节点的next节点(高位数节点)为下次递归返回值,再返回当前节点作为上一个节点(低位节点)的next节点,
如果有一个链表为空,这里假设L2为空,如果递归时,低位节点不存在进位情况,则直接返回L1即可,如果存在进位,就更新L1节点值,并且如果更新L1节点值导致还需要继续进位,则继续递归下去
如果链表全为空,如果此时还需要进位,就返回一个开辟的值位L的新节点,如果不需要进位,直接返回空指针
LinkList addTwoNumbers(LinkList L1, LinkList L2)
{
// // 如果两个链表都是空的,返回空
if (L1 == NULL && L2 == NULL)
return NULL;
// 如果链表1为空,直接返回链表2
if (L1 == NULL)
return L2;
// 如果链表2为空,直接返回链表1
if (L2 == NULL)
return L1;
// 初始化两个链表的当前节点指针cur1, cur2,和返回链表的头尾指针
LNode* cur1 = L1, *cur2 = L2, *head = NULL, *tail = NULL;
// 临时变量,用来保存当前的进位
int tmp = 0;
while (cur1 && cur2)
{
// 创建新节点保存当前的计算结果
LNode* ret = (LinkList)malloc(sizeof(LNode));
// 当前节点的值是两个链表对应节点的和加上进位(tmp)
ret->data = (cur1->data + cur2->data + tmp) % 10;
// 如果头节点为空,表示链表为空,设置头尾指针
if (head == NULL)
{
tail = ret;
head = tail;
}
else
{
// 如果链表非空,将新节点添加到尾部
tail->next = ret;
tail = ret;
}
// 计算新的进位
tmp = (cur1->data + cur2->data + tmp) / 10;
// 移动到下一个节点
cur1 = cur1->next;
cur2 = cur2->next;
}
// 如果L2链表长于L1链表,处理L2剩余部分
if (cur2)
{
// 将cur1指向cur2,继续处理
cur1 = cur2;
}
// 处理L1剩余部分
while (cur1)
{
// 创建新节点保存当前的计算结果
LNode* ret = (LinkList)malloc(sizeof(LNode));
// 当前节点的值是L1当前节点的值加上进位(tmp)
ret->data = (cur1->data + tmp) % 10;
// 更新进位
tmp = (cur1->val + tmp) / 10;
// 移动到下一个节点
cur1 = cur1->next;
// 将新节点添加到尾部
tail->next = ret;
tail = ret;
}
// 如果有剩余进位,添加一个新节点表示进位
if (tmp)
{
// 创建新节点保存进位
LNode* ret = (LinkList)malloc(sizeof(LNode));
ret->data = tmp;
// 将进位节点添加到尾部
tail->next = ret;
tail = ret;
}
// 最后将尾节点的next指针置为空,表示链表结束
tail->next = NULL;
// 返回链表的头节点
reeturn head;
}

被折叠的 条评论
为什么被折叠?



