資料結構——迴圈連結串列、僅設尾指標的迴圈連結串列、約瑟夫環
阿新 • • 發佈:2019-01-09
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 }