1. 程式人生 > >資料結構——迴圈連結串列、僅設尾指標的迴圈連結串列、約瑟夫環

資料結構——迴圈連結串列、僅設尾指標的迴圈連結串列、約瑟夫環

  1 //迴圈連結串列,連結串列的尾結點的link域中不是NULL,而是存放了指標連結串列開始結點的指標
  2 ////設p是在迴圈連結串列中逐個結點檢測指標,則在判斷p是否達到連結串列的鏈尾時p->link == first
  3 
  4 
  5 //迴圈連結串列的結構定義
  6 typedef int DataType;
  7 typedef struct node//迴圈連結串列定義
  8 {
  9     DataType data;//結點資料
 10     struct node *link;//後繼結點指標
 11 }CirNode, *CirList;
 12 
 13 //迴圈連結串列的插入演算法
 14 int Insert(CirNode *first, int i, DataType x)
 15 {//將新元素x插入在迴圈連結串列中第i(1<=i)個結點位置。如果插入失敗函式返回0,否則函式返回1.
 16     if(i<1)
 17         return 0;
 18     CirNode *p = first, *q;
 19     int k = 0;
 20     while(p->link != first && k< i-1)//定位於第i-1個結點,如果i超出表長度則插入到鏈尾
 21     {
 22         p = p->link;
 23         k++;
 24     }
 25     q = new CirNode;//建立新結點用q指示
 26     if(!q){cerr<<"儲存分配錯誤!\n"; exit(1);}
 27     q->data = x;
 28     q->link = p->link;//將*q連結在*p之後
 29     p->link = p;
 30     return 1;//插入成功
 31 }
 32 

 33 //迴圈連結串列的刪除演算法
 34 int Remove(CirList& first, int i, DataType& x)
 35 {//將連結串列中的第i個元素刪去,通過引用型引數x返回該元素的值
 36 //如果i不合理則刪除失敗,函式返回0, 否則函式返回1
 37     if(i<1)return 0;//i太小,不合理
 38     CirNode *p = first, *q;
 39     int k = 0;
 40     while(p->link != first && k < i-1)
 41     {
 42         p = p->link;
 43         k++;
 44     }
 45     //if(p->link == L)//i太大,被刪結點不存在
 46      //   return 0;
 47     q = p->link;//用q儲存被刪結點地址
 48     p->link = q->link;//重新連結,將被刪結點從鏈中摘下
 49     x = q->data;//取出被刪結點的資料
 50     delete q;//釋放結點
 51     return 1;
 52 }
 55 //僅設尾指標的迴圈連結串列
 56 //不用表頭指標而用一個指向表尾結點的指標rear標識,可以將插入和刪除的時間複雜度提高到O(l)
 57 //刪除迴圈連結串列的指標p所指示的結點
 58 int Remove(CirNode* &p, DataType& x)
 59 {//將連結串列中的指標p所指示結點的元素刪去,通過引用型引數x返回該元素的值
 60 
 61     CirNode *q = p->link;
 62     x = p->data;//取出p結點的元素
 63     p->data = q->data;//下一結點的元素複製給被刪結點
 64     p->link = q->link;//重新連結,將下一結點從鏈中摘下
 65     delete q;//釋放下一結點
 66     return 1;
 67 }
 68 //在迴圈尾端插入一個由newNode所指示的新結點
 69 int Insert(CirNode* &p, DataType& x)
 70 {//rear為尾指標
 71     CirNode *newNode;
 72     newNode->data = x;
 73     newNode->link = rear->link;
 74     rear->link = newNode;
 75 }

 78 //求解約瑟夫環問題
 79 
 80 void Josephus(CirNode* & Js, int n, int m)
 81 {
 82     CirNode *p = Js, *pre = NULL;
 83     for(int i = 0; i<n-1; i++)//執行n-1趟虛迴圈
 84     {
 85         for(int j = 0; j<m; j++)//令p向後移動m-1個結點
 86         {
 87             pre = p;
 88             p=p->link;
 89         }
 90         cout<<"出列的人"<<p->data<<endl;//輸出結點*p的資料
 91         pre->link = p->link;
 92         delete p;//刪去結點*p
 93         p = pre->link;
 94     }
 95     cout<<"最終優勝者是:"<<p->data<<endl;//輸出結果
 96 }
 97 int main()
 98 {
 99     CirNode *clist, *last;
100     int n, m;
101     clist = new CirNode;//建立迴圈連結串列頭結點
102     //if(!clist){cerr<<"儲存分配失敗!\n"; exit(1);}
103     clist->link = clist;
104     last = clist;//迴圈連結串列置空
105     cout<<"輸入遊戲者人數和報數間隔:";
106     cin>>n>>m;
107     for(int i=1; i<=n; i++)
108     {
109         last->link = new CirNode;//建立連結串列結點
110         if(!last->link){cerr<<"儲存分配失敗!\n"; exit(1);}
111         last = last->link;//逐個插入結點形成約瑟夫環
112         last->data = i;
113     }
114     Josephus(clist, n, m);//解決約瑟夫環問題
115     return 0;
116 }
117 //演算法時間複雜度O(n*m)

約瑟夫環實現(C語言)

  1 #include"stdio.h"
  2 #include <malloc.h>
  3 
  4 //單鏈表結構體
  5 typedef struct Node
  6 {
  7     int index;
  8     int key;
  9     struct Node *next;
 10 }LinkNode, *LinkList;
 11 
 12 //建立連結串列
 13 LinkList CreatLinkList()
 14 {
 15     LinkList L;
 16     L = (LinkList)malloc(sizeof(Node));
 17     printf("請輸入第一個人的密碼:\n");
 18     int key;
 19     scanf_s("%d",&key);
 20     L->key = key;
 21     L->index = 1;
 22     L->next = L;
 23     Node *tail;
 24     Node *s;
 25     tail = L;
 26 
 27     printf("請輸入構建迴圈單鏈表的長度-1:");//除去已經輸入的第一個人
 28     int len;
 29     scanf_s("%d",&len);
 30 
 31     for (int i = 1; i < len; i++)
 32     {
 33         s = (Node *)malloc(sizeof(Node));
 34         scanf_s("%d", &s->key);
 35         s->index = i + 1;
 36         s->next = tail->next;
 37         tail->next = s;
 38         tail = s;
 39     }
 40     return L;
 41 }
 42 
 43 //約瑟夫環的實現
 44 void yuesef(LinkList L,int Password)
 45 {
 46     int count = 1;
 47     Node *p;
 48     Node *s, *r;
 49     p = L;
 50     while (p->next != p)
 51     {
 52         if (count == Password - 1)
 53         {
 54             printf("下標:%d  密碼:%d\n", p->next->index, p->next->key);
 55             s = p->next;
 56             p->next = s->next;
 57             Password = s->key;
 58             while (Password == 1 && p->next != p)
 59             {
 60                 printf("下標:%d  密碼:%d\n", p->next->index, p->next->key);
 61                 r = p->next;
 62                 p->next = r->next;
 63                 Password = r->key;
 64                 free(r);
 65             }
 66             free(s);
 67             count = 1;
 68             p = p->next;
 69         }
 70         else
 71         {
 72             p = p->next;
 73             count++;
 74         }
 75     }
 76     printf("下標:%d  密碼:%d\n", p->index, p->key);
 77 }
 78 
 79 int main(void)
 80 {
 81     LinkList L;
 82     L = CreatLinkList();
 83     Node *p;
 84     p = L;
 85     printf("%d %d \n", p->index, p->key);
 86     p = p->next;
 87     //單鏈表的遍歷
 88     while (p != L)
 89     {
 90         printf("%d %d \n", p->index, p->key);
 91         p = p->next;
 92     }
 93     printf("請輸入初始關鍵值:\n");
 94     int Password;
 95     scanf_s("%d",&Password);
 96     yuesef(L, Password);
 97     getchar();
 98     getchar();
 99     return 0;
100 }