1. 程式人生 > >《資料結構》進行曲--帶頭結點的單迴圈連結串列的基本操作

《資料結構》進行曲--帶頭結點的單迴圈連結串列的基本操作

單迴圈連結串列

迴圈連結串列的特點是最後一個元素的指標域指向頭結點。


因此對於迴圈連結串列的初始化(設表的頭結點是L, 不再是L->next=NULL,而是L->next=L。迴圈連結串列為空時,頭結點的下一個結點依然是頭結點本身。因此但虛幻連結串列的初始化如下:(資料型別設為int)

//初始化 
int InitList(LinkList &L){
	L=new LNode;
	L->next=L;//非迴圈連結串列的初始化是頭指標的指標域置空 L->next=NULL 
	return 1;
}

所以根據迴圈連結串列的特點,判斷迴圈連結串列是否為空時,只需判斷頭結點的下一個結點是否是頭結點即可:
//判斷連結串列是否為空
int ListEmpty(LinkList L){
	if(L->next==L){
		return 1;//空 
	}else{
		return 0;//非空 
	}
}

從頭檢查每一個結點,若當前結點不是頭結點,則連結串列長度加1,由此可計算連結串列的長度:

//獲取連結串列長度
int ListLength(LinkList L){
	int length=0;
	struct LNode *p;
	p=L->next;
	while(p!=L){//當p不是頭結點時,連結串列長度加1 
		p=p->next;
		++length;
	}
	return length;
} 

//遍歷連結串列
void TraveList(LinkList L){
	struct LNode *p;
	p=L->next;
	printf("遍歷連結串列:\n");
	while(p!=L){//當p不是頭結點時,輸出元素值 
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
} 

使用頭插法和尾插法建立單迴圈連結串列的方法和建立一般單鏈表的操作一樣,區別在於建立空連結串列的語句不同。一般單鏈表是L->next=NULL,而單迴圈連結串列是L->next=L。
//頭插法建立單迴圈連結串列
void CreateList1(LinkList &L,int n){
	//建立長度為n的單迴圈連結串列 
	L=new LNode;
	L->next=L;
	printf("請輸入連結串列元素值:\n");
	for(int i=n;i>0;--i){
		printf("請輸入第%d個元素的值:",i);
		struct LNode *p;
		p=new LNode;//生成新結點
		scanf("%d",&p->data);
		p->next=L->next;;
		L->next=p; 
	}
} 

//尾插法建立單迴圈連結串列
void CreateList2(LinkList &L,int n){
	L=new LNode;
	L->next=L;
	struct LNode *r;
	r=L;
	for(int i=0;i<n;i++){
		printf("請輸入第%d個元素的值:",i+1);
		struct LNode *p;
		p=new LNode;
		scanf("%d",&p->data);
		p->next=L;
		r->next=p;
		r=p;
	}
} 

單迴圈連結串列的刪除操作和一般單鏈表的操作時一樣的。要注意的是單迴圈連結串列的插入操作:
//單迴圈連結串列的刪除操作
int ListDelete(LinkList &L,int location,int &e){
	//刪除L中location位置的元素,並用e返回其值
	 struct LNode *p;
	 p=L;
	 int j=0;
	 while(p->next!=L&&j<location-1){
	 	p=p->next;
	 	++j;
	 }
	 if(p==L||j>location-1){
	 	return 0;
	 }
	 struct LNode *q;
	 q=new LNode;
	 q=p->next;
	 p->next=q->next;
	 e=q->data;
	 delete q;
	 return 1;
} 

//單迴圈連結串列的插入操作
int ListInsert(LinkList &L,int location,int &e){
	//在L的location位置插入元素e
	 struct LNode *p;
	 p=L;
	 int j=0;
	 while(p->next!=L&&j<location-1){
	 <span style="color:#ff0000;">//注意:由於p初始時指向頭結點,所以迴圈的條件是 p->next!=L 
	 //而不是 p!=L 
	 	p=p->next;					  
	 	++j;
	 }
	 if(p==L||j>location-1){
	 	return 0;
	 }
	 struct LNode *s;
	 s=new LNode;
	 s->data=e;
	 s->next=p->next;
	 p->next=s;
	 return 1;
} 

單迴圈連結串列的基本操作的實現:
#include<stdio.h>
#include<iostream>
using namespace std;

#define MAX 100

//儲存結構 
typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList;

//初始化 
int InitList(LinkList &L){
	L=new LNode;
	L->next=L;//非迴圈連結串列的初始化是頭指標的指標域置空 L->next=NULL 
	return 1;
}

//判斷連結串列是否為空
int ListEmpty(LinkList L){
	if(L->next==L){
		return 1;//空 
	}else{
		return 0;//非空 
	}
}

//獲取連結串列長度
int ListLength(LinkList L){
	int length=0;
	struct LNode *p;
	p=L->next;
	while(p!=L){//當p不是頭結點時,連結串列長度加1 
		p=p->next;
		++length;
	}
	return length;
} 

//遍歷連結串列
void TraveList(LinkList L){
	struct LNode *p;
	p=L->next;
	printf("遍歷連結串列:\n");
	while(p!=L){//當p不是頭結點時,輸出元素值 
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
} 

//頭插法建立單迴圈連結串列
void CreateList1(LinkList &L,int n){
	//建立長度為n的單迴圈連結串列 
	L=new LNode;
	L->next=L;
	printf("請輸入連結串列元素值:\n");
	for(int i=n;i>0;--i){
		printf("請輸入第%d個元素的值:",i);
		struct LNode *p;
		p=new LNode;//生成新結點
		scanf("%d",&p->data);
		p->next=L->next;;
		L->next=p; 
	}
} 

//尾插法建立單迴圈連結串列
void CreateList2(LinkList &L,int n){
	L=new LNode;
	L->next=L;
	struct LNode *r;
	r=L;
	for(int i=0;i<n;i++){
		printf("請輸入第%d個元素的值:",i+1);
		struct LNode *p;
		p=new LNode;
		scanf("%d",&p->data);
		p->next=L;
		r->next=p;
		r=p;
	}
} 

//單迴圈連結串列的插入操作
int ListInsert(LinkList &L,int location,int &e){
	//在L的location位置插入元素e
	 struct LNode *p;
	 p=L;
	 int j=0;
	 while(p->next!=L&&j<location-1){
	 //注意:由於p初始時指向頭結點,所以訓話的條件是 p->next!=L 
	 //而不是 p!=L 
	 	p=p->next;					  
	 	++j;
	 }
	 if(p==L||j>location-1){
	 	return 0;
	 }
	 struct LNode *s;
	 s=new LNode;
	 s->data=e;
	 s->next=p->next;
	 p->next=s;
	 return 1;
} 

//單迴圈連結串列的刪除操作
int ListDelete(LinkList &L,int location,int &e){
	//刪除L中location位置的元素,並用e返回其值
	 struct LNode *p;
	 p=L;
	 int j=0;
	 while(p->next!=L&&j<location-1){
	 	p=p->next;
	 	++j;
	 }
	 if(p==L||j>location-1){
	 	return 0;
	 }
	 struct LNode *q;
	 q=new LNode;
	 q=p->next;
	 p->next=q->next;
	 e=q->data;
	 delete q;
	 return 1;
} 
int main(){
	LinkList L;
	
	if(InitList(L)){
		printf("初始化成功!\n");
	}else{
		printf("初始化失敗!\n");
	}
	
	if(ListEmpty(L)){
		printf("當前連結串列為空.\n");
	}else{
		printf("連結串列非空.\n");
	}
	
	printf("請輸入連結串列長度:");
	int n;
	scanf("%d",&n);
	//CreateList1(L,n);
	CreateList2(L,n);
	
	if(ListEmpty(L)){
		printf("當前連結串列為空.\n");
	}else{
		printf("連結串列非空.\n");
	}
	
	printf("當前連結串列長度是:%d\n",ListLength(L));
	TraveList(L);
	
	printf("請輸入插入位置和值:\n");
	int location,e;
	scanf("%d%d",&location,&e);
	if(ListInsert(L,location,e)){
		printf("插入成功\n");
	}else{
		printf("插入失敗\n");
	}
	TraveList(L);
	
	printf("請輸入刪除元素的位置:\n");
	int e1,location1;
	scanf("%d",&location1);
	if(ListDelete(L,location1,e1)){
		printf("刪除成功\n");
		printf("刪除的元素值為:%d\n",e1);
	}else{
		printf("刪除失敗\n");
	}
	TraveList(L);
} 


有錯誤敬請讀者指出。