今天对链表有了更深入的了解,昨天学的链表是单向的,你会发现一个问题就是如果链表进行p = p->next;后p会找不到之前的结点。这就会引入双向链表的概念,它拥有2个指针域,一个数据域,头结点定义的时候,指针域指的是链表长度,设置为0,假定2个指针域一个为prev一个为next,那么头结点的指针域初始化如下p->next = NULL; p->prev = NULL;然后就是循环链表了,循环单链表,循环双链表,它们唯一和之前的不同在于,头结点的prev指针指向尾结点,尾结点的next指针指向头结点。还需要注意的是循环链表在插入删除的时候比普通链表更加麻烦,但也跟我们带来了许多便利。 下面是今天的xmid
练习:
main.c
1.双向链表按元素删除
LinklistDouble *p = LinklistDoubleSpace();
p->len = 0;
p->prev == NULL;
p->next == NULL;
while(1){
printf("==========双向链表=========\n");
printf("1插入\t2输出\n3查找\t4删除\n5退出\n");
int choice;
printf("请输入操作: \n");
scanf("%d",&choice);
getchar();
if(choice == 1){
LinklistDoubleInsert(p);
p->len ++;
}
else if(choice == 2){
LinklistDoublePrint(p);
}
else if(choice == 3){
LinklistDouble *q = LinklistDoubleSearch(p);
if(q == NULL){
printf("查找失败\n");
}
else{
printf("查找成功,该元素的地址是: %p\n",q);
}
}
else if(choice == 4){
LinklistDoubleDelete(p);
}
else if(choice == 5){
break;
}
}
free(p);
p == NULL;
2.循环双向链表按位置插入
printf("==========双向循环链表=========\n");
LinklistDoubleLoop *k = LinklistDoubleLoopSpace();
k->len = 0;
k->next = k;
k->prev = k;
while(1){
printf("1插入\t2输出\n3退出\n");
int choice;
printf("请输入操作: \n");
scanf("%d",&choice);
getchar();
if(choice == 1){
LinklistDoubleLoopInsert(k);
}
else if(choice == 2){
LinklistDoubleLoopPrint(k);
}
else if(choice == 3){
break;
}
}
free(k);
k == NULL;
3.实现约瑟夫环
4.删除链表中的所有结点
5.实现单向链表的简单选择排序
printf("==========单向循环链表=========\n");
SinglyLinklist *w = SinglyLinklistSpace();
w->len = 0;
w->next = w;
while(1){
printf("1插入\t2输出\n3约瑟夫\t4排序\n5逆置\t6退出\n");
int choice;
printf("请输入操作: ");
scanf("%d",&choice);
getchar();
if(choice == 1){
SinglyLinklistInsert(w);
}
else if(choice == 2){
SinglyLinklistPrint(w);
}
else if(choice == 3){
SinglyLinklistJoseph(w);
w->next = w;
}
else if(choice == 4){
SinglyLinklistSorting(w);
}
else if(choice == 5){
SinglyLinklistNiZhi(w);
}
else if(choice == 6){
break;
}
}
head.h
1.双向链表按元素删除
typedef struct node {
union{
int len;
char data;
};
struct node *prev;
struct node *next;
}LinklistDouble;
LinklistDouble *LinklistDoubleSpace();
void LinklistDoubleInsert(LinklistDouble *p);
void LinklistDoublePrint(LinklistDouble *p);
LinklistDouble *LinklistDoubleSearch(LinklistDouble *p);
void LinklistDoubleDelete(LinklistDouble *p);
2.循环双向链表按位置插入
typedef struct node2 {
union{
int len;
char data;
};
struct node2 *prev;
struct node2 *next;
}LinklistDoubleLoop;
LinklistDoubleLoop *LinklistDoubleLoopSpace();
LinklistDoubleLoop *LinklistDoubleLoopSearch(LinklistDoubleLoop *p);
void LinklistDoubleLoopInsert(LinklistDoubleLoop *p);
void LinklistDoubleLoopPrint(LinklistDoubleLoop *p);
3.实现约瑟夫环
4.删除链表中的所有结点
5.实现单向链表的简单选择排序
typedef struct node3{
union{
int len;
char data;
};
struct node3 *next;
}SinglyLinklist;
SinglyLinklist *SinglyLinklistSpace();
void SinglyLinklistInsert(SinglyLinklist *p);
void SinglyLinklistPrint(SinglyLinklist *p);
void SinglyLinklistJoseph(SinglyLinklist *p);
void SinglyLinklistSorting(SinglyLinklist *p);
void SinglyLinklistNiZhi(SinglyLinklist *p);
fun.c
1.双向链表按元素删除
LinklistDouble *LinklistDoubleSpace(){
LinklistDouble *p = (LinklistDouble *)malloc(sizeof(LinklistDouble));
if(p == NULL){
return NULL;
}
return p;
}
void LinklistDoubleInsert(LinklistDouble *p){
LinklistDouble *k = LinklistDoubleSpace();
printf("请输入新的数据: ");
scanf("%c",&k->data);
getchar();
k->next = p->next;
k->prev = p;
if(k->next){
k->next->prev = k;
}
p->next = k;
printf("插入成功!\n");
}
void LinklistDoublePrint(LinklistDouble *p){
while(p->next){
p = p->next;
printf("%c ",p->data);
}
printf("\n");
while(p->prev){
printf("%c ",p->data);
p = p->prev;
}
printf("\n");
}
LinklistDouble *LinklistDoubleSearch(LinklistDouble *p){
if(!(p->next)){
printf("该链表空了,不能操作。\n");
return NULL;
}
printf("请输入你要查找的元素: ");
char search;
scanf("%c",&search);
getchar();
while(p->next != NULL && p->next->data != search){
p = p->next;
}
return p->next;
}
void LinklistDoubleDelete(LinklistDouble *p){
LinklistDouble *q = LinklistDoubleSearch(p);
if(q == NULL){
printf("删除失败!\n");
return;
}
q->prev->next = q->next;
if(q->next)
q->next->prev = q->prev;
p->len --;
printf("删除成功!\n");
}
2.循环双向链表按位置插入
LinklistDoubleLoop *LinklistDoubleLoopSpace(){
LinklistDoubleLoop *p = (LinklistDoubleLoop *)malloc(sizeof(LinklistDoubleLoop));
if(p == NULL){
return NULL;
}
return p;
}
LinklistDoubleLoop *LinklistDoubleLoopSearch(LinklistDoubleLoop *p){
printf("请输入插入的位置: ");
int mid;
scanf("%d",&mid);
getchar();
if(mid < 1 || mid > p->len + 1){
return NULL;
}
while(mid > 1){
p = p->next;
mid --;
}
return p;
}
void LinklistDoubleLoopInsert(LinklistDoubleLoop *p){
LinklistDoubleLoop *q = LinklistDoubleLoopSearch(p);
if(q == NULL){
printf("插入位置不合法!\n");
return;
}
LinklistDoubleLoop *k = LinklistDoubleLoopSpace();
printf("请输入插入的值: ");
scanf("%c",&k->data);
getchar();
k->next = q->next;
k->prev = q;
q->next->prev = k;
q->next = k;
p->len ++;
printf("插入成功\n");
}
void LinklistDoubleLoopPrint(LinklistDoubleLoop *p){
LinklistDoubleLoop *q = p;
printf("链表如下: \n");
while(p->next != q){
p = p->next;
printf("%c ",p->data);
}
printf("\n");
while(p->prev != q){
printf("%c ",p->data);
p = p->prev;
}
printf("\n");
}
3.实现约瑟夫环
4.删除链表中的所有结点
5.实现单向链表的简单选择排序
SinglyLinklist *SinglyLinklistSpace(){
SinglyLinklist *p = (SinglyLinklist *)malloc(sizeof(SinglyLinklist));
if(p == NULL){
return NULL;
}
return p;
}
void SinglyLinklistInsert(SinglyLinklist *p){
SinglyLinklist *k = SinglyLinklistSpace();
printf("请输入插入的值: ");
scanf("%c",&k->data);
getchar();
p->len ++;
SinglyLinklist *q = p;
while(p->next != q && p->next->data < k->data){
p = p->next;
}
printf("%c\n",p->data);
k->next = p->next;
p->next = k;
printf("插入成功\n");
}
void SinglyLinklistPrint(SinglyLinklist *p){
SinglyLinklist *q = p;
while(p->next != q){
p = p->next;
printf("%c ",p->data);
}
printf("\n");
}
void SinglyLinklistJoseph(SinglyLinklist *p){
SinglyLinklist *q = p;
printf("请输入数到第几个移出链表: \n");
int n;
scanf("%d",&n);
getchar();
while(q->len){
for(int i = 0; i < n-1; i ++){
p = p->next;
if(p == q){
i --;
}
}
SinglyLinklist *k = p->next;
if(k == q){
k = q->next;
}
printf("%c ",k->data);
p->next = k->next;
free(k);
k == NULL;
q->len --;
}
printf("\n");
}
void SinglyLinklistSorting(SinglyLinklist *p){
SinglyLinklist *q = p->next;
for(;q != p; q = q->next){
SinglyLinklist *max = q;
for(SinglyLinklist *w = q->next; w != p; w = w->next){
if(max->data < w->data){
max = w;
}
}
if(max != q){
int mid = max->data;
max->data = q->data;
q->data = mid;
}
}
}
void SinglyLinklistNiZhi(SinglyLinklist *p){
SinglyLinklist *q = p->next;
p->next = p;
while(q != p){
SinglyLinklist *k = q;
q = q->next;
k->next = p->next;
p->next = k;
}
}