单向循环链表(头节点和尾节点形成循环)
创建头节点
Loop* create_loop()
{
Loop* head=(Loop*)malloc(sizeof(Loop));
if(head==NULL){
printf("创建头结点失败\n");
return NULL;
}
head->next=head;
head->text.len=0;
return head;
}
从头部插入数据
void insert_loopBefore(Loop* head,dataType data)
{
Loop* temp=(Loop*)malloc(sizeof(Loop));
if(temp==NULL){
printf("创建结点失败\n");
return;
}
temp->text.data=data;
temp->next=head->next;
head->next=temp;
head->text.len++;
return;
}
从尾部插入数据
void insert_loopAfter(Loop* head,dataType data)
{
Loop* temp=(Loop*)malloc(sizeof(Loop));
if(temp==NULL){
printf("创建结点失败\n");
return;
}
temp->text.data=data;
Loop* p=head;
while(p->next!=head){
p=p->next;
}
p->next=temp;
temp->next=head;
head->text.len++;
return;
}
遍历链表
void travel_loopList(Loop* head)
{
Loop* p=head;
while(p->next!=head){
p=p->next;
printf("%d ",p->text.data);
}
putchar(10);
return;
}
从头部删除数据
void delete_loopBefore(Loop* head)
{
if(head==NULL || head->next==head){
printf("链表错误或链表为空\n");
return;
}
Loop* temp=head->next;
head->next=head->next->next;
head->text.len--;
free(temp);
temp=NULL;
return;
}
从尾部删除数据
void delete_loopAfter(Loop* head)
{
if(head==NULL || head->next==head){
printf("链表错误或链表为空\n");
return;
}
Loop* p=head;
while(p->next->next!=head){//找倒数第二个
p=p->next;
}
Loop* temp=p->next;
p->next=head;
head->text.len--;
free(temp);
return;
}
头文件
#ifndef __LOOPLINK_H__
#define __LOOPLINK_H__
#include <stdlib.h>
#include <stdio.h>
typedef int dataType;
typedef struct loop{
union{
int len;
dataType data;
} text;
struct loop* next;
} Loop;
Loop* create_loop();
void insert_loopBefore(Loop* head,dataType data);
void insert_loopAfter(Loop* head,dataType data);
void travel_loopList(Loop* head);
void delete_loopBefore(Loop* head);
void delete_loopAfter(Loop* head);
#endif
主函数体
#include "./03_loopLink.h"
int main(int argc, const char *argv[])
{
Loop* head=create_loop();
insert_loopBefore(head,10);
insert_loopBefore(head,20);
insert_loopBefore(head,70);
insert_loopBefore(head,8);
travel_loopList(head);
delete_loopBefore(head);
delete_loopAfter(head);
travel_loopList(head);
return 0;
}
双向链表(可以向前访问也可以向后访问)
创建头结点
Bothway* create_bothway()
{
Bothway* head=(Bothway*)malloc(sizeof(Bothway));
if(head==NULL){
printf("创建头结点失败\n");
return NULL;
}
memset(head,0,sizeof(Bothway));
return head;
}
从头部插入数据
void insert_bothwayBefore(Bothway* head,datatype data)
{
Bothway* temp=(Bothway*)malloc(sizeof(Bothway));
memset(temp,0,sizeof(Bothway));
temp->text.data=data;
if(head->next!=NULL){
temp->next=head->next;
head->next=temp;
temp->next->prev=temp; //如果head后面没有结点,temp->next->prev是空
//必出段错误
temp->prev=head;
}else{
temp->prev=head;
head->next=temp;
}
head->text.len++;
return;
}
从尾部插入数据
void insert_bothwayAfter(Bothway* head,datatype data)
{
Bothway* temp=(Bothway*)malloc(sizeof(Bothway));
memset(temp,0,sizeof(Bothway));
temp->text.data=data;
Bothway* p=head;
while(p->next!=NULL){
p=p->next;
}
p->next=temp;
temp->prev=p;
head->text.len++;
return;
}
按位置插入数据
void insert_bothwayByPos(Bothway* head,datatype data,int pos)
{
if(pos>head->text.len+1 || pos<1){
printf("插入位置不合法\n");
return;
}
Bothway* temp=(Bothway*)malloc(sizeof(Bothway));
memset(temp,0,sizeof(Bothway));
temp->text.data=data;
Bothway* p=head;
for(int i=0;i<pos-1;i++){ //i从1开始
p=p->next;
}
if(p->next==NULL){ //尾插
p->next=temp;
temp->prev=p;
}else{ //头插
p->next->prev=temp;
temp->prev=p;
temp->next=p->next;
p->next=temp;
}
head->text.len++;
return;
}
按位置删除数据
void delete_bothwayByPos(Bothway* head,int pos)
{
if(head==NULL || head->next==NULL){
printf("链表错误或为空\n");
return;
}
if(pos>head->text.len || pos<1){
printf("删除位置不合法\n");
return;
}
Bothway* p=head;
for(int i=0;i<pos-1;i++){
p=p->next;
}
if(p->next==NULL){//尾删
p->prev->next=NULL;
free(p);
}else{//头删
Bothway* temp=p->next;
p->next->next->prev=p;
p->next=p->next->next;
free(temp);
}
head->text.len--;
return;
}
遍历数据
void travel_bothway(Bothway* head)
{
Bothway* p=head;
while(p->next!=NULL){
p=p->next;
printf("%d ",p->text.data);
}
putchar(10);
return;
}
从头部删除数据
void delete_bothwayBefore(Bothway* head)
{
if(head==NULL || head->next==NULL){
printf("链表错误或为空\n");
return;
}
Bothway* temp=head->next;
if(head->next->next==NULL){ //尾删
head->next=NULL;
}else{ //头删
head->next=head->next->next;
temp->next->prev=head;
}
head->text.len--;
free(temp);
temp=NULL;
return;
}
从尾部删除数据
void delete_bothwayAfter(Bothway* head)
{
if(head==NULL || head->next==NULL){
printf("链表错误或为空\n");
return;
}
Bothway* p=head;
while(p->next!=NULL){
p=p->next;
}
p->prev->next=NULL; //前一个结点的next
free(p);
head->text.len--;
return;
}
头文件
#ifndef __BOTHWAY_H__
#define __BOTHWAY_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int datatype;
typedef struct bothway{
struct bothway* prev;
union{
int len;
datatype data;
} text;
struct bothway* next;
} Bothway;
Bothway* create_bothway();
void insert_bothwayBefore(Bothway* head,datatype data);
void insert_bothwayAfter(Bothway* head,datatype data);
void insert_bothwayByPos(Bothway* head,datatype data,int pos);
void travel_bothway(Bothway* head);
void delete_bothwayBefore(Bothway* head);
void delete_bothwayAfter(Bothway* head);
void delete_bothwayByPos(Bothway* head,int pos);
#endif
主函数体
#include "./03_bothway.h"
int main(int argc, const char *argv[])
{
Bothway* head=create_bothway();
insert_bothwayBefore(head,10);
insert_bothwayBefore(head,20);
insert_bothwayAfter(head,30);
insert_bothwayAfter(head,40);
insert_bothwayByPos(head,50,1);
insert_bothwayByPos(head,60,5);
/* travel_bothway(head);
delete_bothwayBefore(head);
delete_bothwayBefore(head);
delete_bothwayAfter(head);
delete_bothwayAfter(head);
delete_bothwayByPos(head,1);
travel_bothway(head);
*/
return 0;
}
双向循环链表(头节点和尾节点形成循环)
创建头结点
Loop* create_loopBothway()
{
Loop* head=(Loop*)malloc(sizeof(Loop));
if(NULL==head){
printf("创建结点失败\n");
return NULL;
}
memset(head,0,sizeof(Loop));
head->prev=head;
head->next=head;
return head;
}
判断头节点是否正确
int list_isTrue(Loop* head)
{
if(NULL==head){
printf("链表错误\n");
return 1;
}
return 0;
}
从头部插入数据
void insert_loopBothwayBefore(Loop* head,datatype data)
{
if(list_isTrue(head)) return;
Loop* temp=(Loop*)malloc(sizeof(Loop));
if(NULL==temp){
printf("创建结点失败\n");
return;
}
memset(temp,0,sizeof(Loop));
temp->text.data=data;
if(head->next==head){ //尾插
head->next=temp;
temp->next=head;
temp->prev=head;
head->prev=temp;
}else{ //头插
temp->next=head->next;
head->next=temp;
temp->next->prev=temp;
temp->prev=head;
}
head->text.len++;
return;
}
从尾部插入数据
void insert_loopBothwayAfter(Loop* head,datatype data)
{
if(list_isTrue(head)) return;
Loop* temp=(Loop*)malloc(sizeof(Loop));
if(NULL==temp){
printf("创建结点失败\n");
return;
}
memset(temp,0,sizeof(Loop));
temp->text.data=data;
Loop* p=head;
while(p->next!=head){
p=p->next;
}
temp->next=p->next;
temp->prev=p;
p->next=temp;
head->text.len++;
return;
}
按位置插入数据
void insert_loopBothwayBypos(Loop* head,datatype data,int pos)
{
if(list_isTrue(head)) return;
if(pos<1 ||pos>head->text.len+1){
printf("插入位置不合法\n");
return;
}
Loop* temp=(Loop*)malloc(sizeof(Loop));
if(NULL==temp){
printf("创建结点失败\n");
return;
}
memset(temp,0,sizeof(Loop));
temp->text.data=data;
Loop* p=head;
for(int i=0;i<pos-1;i++){
p=p->next;
}
if(p->next==head){ //尾插
temp->next=head;
temp->prev=p;
p->next=temp;
}else{ // 头插
p->next->prev=temp;
temp->prev=p;
temp->next=p->next;
p->next=temp;
}
head->text.len++;
return;
}
遍历数据
void travel_loopBothway(Loop* head)
{
Loop* p=head;
while(p->next!=head){
p=p->next;
printf("%d ",p->text.data);
}
return;
}
从头部删除数据
void delete_bothwayBefore(Loop* head)
{
if(list_isTrue(head)) return;
Loop* temp=head->next;
if(temp->next==head){ //尾删
head->next=head;
head->prev=head;
}else{ //头删
head->next=temp->next;
temp->next->prev=head;
}
free(temp);
temp=NULL;
head->text.len--;
return;
}
从尾部删除数据
void delete_bothwayAfter(Loop* head)
{
if(list_isTrue(head)) return;
Loop* p=head;
while(p->next!=head){
p=p->next;
}
p->prev->next=head;
free(p);
head->text.len--;
return;
}
按位置删除数据
void delete_bothwayByPos(Loop* head,int pos)
{
if(list_isTrue(head)) return;
Loop* p=head;
for(int i=0;i<pos;i++){
p=p->next;
}
if(p->next==head){//尾删
p->prev->next=head;
}else{//头删
p->next->prev=p->prev;
p->prev->next=p->next;
}
free(p);
head->text.len--;
return;
}
约瑟夫问题
joseph(约瑟夫)问题
1.设编号分别为:1,2,...,n的n个人围坐一圈。
2.约定序号为k (1sksn) 的人从1开始计数,数到m的那个人出列,
3.他的下一位又从1开始计数,数到m的那个人又出列,依次类推,直到所有人出列为止。
例如,8个人围坐一圈,约定从第3个人开始编号为1,数到第4个人出列。
出列后原来第5个人计算为1.n=8,k=3,m=4,最终出队的结果是6 2 7 4 3 5 18
用单向循环链表来做
void joseph(int n,int k,int m)
{
//拼装约瑟夫环
Loop* head=create_loop();
for(int i=1;i<=n;i++){
insert_loopAfter(head,i);
}
Loop* p=head;
while(p->next!=head){
p=p->next;
}
p->next=head->next; //形成环
p=head;//重置指针
head=head->next;//将头结点置为第一个结点
free(p);
p=head;//重置指针到第一个结点
for(int i=1;i<k;i++){
p=p->next;
}
printf("k=%d\n",p->text.data);
while(p->next!=p){ //当结点指向自己就说明只剩一个结点
for(int i=0;i<m-2;i++){ //找到要删除的前一个:-1 从1开始:-1 共-2
p=p->next;
}
printf("Detele:%d\n",p->next->text.data);
Loop* temp=p->next;
p->next=p->next->next;
free(temp);
p=p->next;
}
printf("Delete:%d\n",p->text.data);
return;
}