引入
前面我们简单了解了一下双链表,以及在插入和删除时的一些变化。这一节,我们就跟着一个凯撒密码,来看看双循环链表的初始化、插入、操作结点等过程。
凯撒密码
凯撒密码是一种代换密码。据说凯撒是率先使用加密函的古代将领之一,因此这种加密方法被称为凯撒密码。他的基本思想是
- 通过把字母移动一定的位数来实现加密和解密。
- 明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。
- 当偏移量是4的时候,所有的字母A将被替换成E,B变成F,以此类推W将变成A,X变成B,Y变成C,Z 变成 D。
- 而这个偏移量就是凯撒密码加密和解密的密钥。
例题
有26个英文字母,我们需要设计一个程序
- 用户输入可为正负的正整数
- 如果是正数,那从左边取 N 位正整数移动到表尾
- 如果是负数,那从右边取 N 位正整数移动到表头
输入 4
初始化:ABCDEFGHIJKLMNOPQRSTUVWXYZ
改变为:FGHIJKLMNOPQRSTUVWXYZABCDE输入-5
初始化:ABCDEFGHIJKLMNOPQRSTUVWXYZ
改变为:VWXYZABCDEFGHIJKLMNOPQRSTU
初始化双链表
第一步:我们先初始化这个由 A~Z 组成的双循环链表。
#include <stdio.h>
#include <stdlib.h>
#define NUM 26
#define LEN sizeof(struct WordList)
// 构建一个双循环链表结点的结构体
struct WordList{
char word;
struct WordList *prior;
struct WordList *next;
};
// 开始初始化这个结构体,让26个字母插入,并形成双循环链表
struct WordList *init(void){
struct WordList *w,*temp,*head;
int i=0; //用于计数
w=(struct WordList *)malloc(LEN);
head=temp=w;
//上面用于处理好头部
while(i<NUM){
w->word='A'+i; //赋值
w->prior=temp; //前驱是 w 的替身 temp
temp->next=w; //后继是 w
temp=w; //让 temp 再次成为 w 的替身
w=(struct WordList *)malloc(LEN); //w重新分配内存空间
i++; //计数加加
}
temp->next=head; //最后一个结点指向头部
head->prior=temp; //头部的前驱指向尾部,形成闭环
return head; //返回头部地址
}
这一步初始化很简单,记住
- 头部处理好,头部在开始等于头结点,结尾需要将头部的前驱指向尾巴
- 顺序不要错,先新结点,再老节点,避免出错
凯撒密码表操作
其实这个比较简单,就是让上面初始化好的指针的头部稍稍移动一下位置
struct WordList *caesar(struct WordList *w , int n){
// 如果输入的大于0,那就是指针向后移动几位,那就会从 n+1 位开始输出了
if(n>0){
do{
w=w->next;
}while(--n);
}
// 如果输入的小于0,那就是指针向前移动几位,那就会从 n-1 位开始输出了
if(n<0){
do{
w=w->prior;
}while(++n);
}
return w; //把指针位置移动之后的地址返回
}
思路
- 我们要想到,既然是循环链表,那么谁都可以是「头指针」
- 你把「头指针」移动到哪里就从哪里输出
最终代码实现
#include <stdio.h>
#include <stdlib.h>
#define NUM 26
#define LEN sizeof(struct WordList)
// 构建一个双循环链表结点的结构体
struct WordList{
char word;
struct WordList *prior;
struct WordList *next;
};
// 开始初始化这个结构体,让26个字母插入,并形成双循环链表
struct WordList *init(void){
struct WordList *w,*temp,*head;
int i=0; //用于计数
w=(struct WordList *)malloc(LEN);
head=temp=w;
//上面用于处理好头部
while(i<NUM){
w->word='A'+i; //赋值
temp->next=w; //后继是 w
w->prior=temp; //前驱是 w 的替身 temp
temp=w; //让 temp 再次成为 w 的替身
w=(struct WordList *)malloc(LEN); //w重新分配内存空间
i++; //计数加加
}
temp->next=head; //最后一个结点指向头部
head->prior=temp; //头部的前驱指向尾部,形成闭环
return head; //返回头部地址
}
void print_word(struct WordList *w){
struct WordList *head;
head=w;
do{
printf("%c ",w->word);
}while((w=w->next)!=head);
}
struct WordList *caesar(struct WordList *w , int n){
if(n>0){
do{
w=w->next;
}while(--n);
}
if(n<0){
do{
w=w->prior;
}while(++n);
}
return w;
}
int main(){
struct WordList *word_p;
int n;
word_p=init();
printf("请输入一个整数:\n");
scanf("%d",&n);
word_p=caesar(word_p,n);
print_word(word_p);
}
尾巴
这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。
评论