【數據結構與算法 2】(單循環鏈表)快慢指針實現查找單循環鏈表中間數據

本文是在《【數據結構與算法 1】(單鏈表)快慢指針實現查找單鏈表中間數據
的基礎上,由單鏈表修改爲單循環鏈表,修改點不多,執行結果如下:
在這裏插入圖片描述

代碼如下,對應的修改點也標註出來了,詳細如下:


// 單鏈表實現方式 
// 利用快慢指針,查找單鏈表的中間節點 

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>


// 定義單鏈表結構體,並構建結構對象 ListNode 和 指向結構的指針LinkList 
typedef struct ListNode{
	int data;
	struct ListNode *next; 
}ListNode, *LinkList;

// 創建鏈表 
void Create_List(LinkList head)
{
	int temp;
	LinkList p, end_p=head;
	
	printf("請輸入節點值,以任意非數字結尾:\n");
	// 刷新輸入緩衝區 
	fflush(stdin);
	
	// 根據輸入的值,循環動態創建鏈表,直到非數字結束 
	while( scanf("%d", &temp) == 1){
		
		//printf("temp = %d\n", temp);
		p = (LinkList) malloc(sizeof(ListNode));
		p->data = temp;
		
		//尾插法 					// 修改點1
		end_p->next = p;
		p->next = head;
		end_p = end_p->next; 

		//  刷新輸入緩衝區
		fflush(stdin);
	}
} 

// 清空鏈表
void Delete_List(LinkList head){
	LinkList temp;
	int i=0; 
	
	while(head->next != head){ 		// 修改點2
		temp = head->next;
		head->next = temp->next;
		
		printf("刪除鏈表數據 [%d] (%d) temp=%p\n", i, temp->data,temp); 
		free(temp);
		i++;
	}
}

int Get_List_Len(LinkList head)
{
	LinkList temp;
	int i = 0;
	
	temp = head->next;
	while(temp != head)			// 修改點3
		i++;
		temp = temp->next; 
	}
	return i;
}

void Print_List(LinkList head)
{
	LinkList p;
	int i = 0;
	
	p = head->next;
	
	if(p == head){ 				// 修改點4
		printf("鏈表爲空\n");
		return; 
	}
	
	printf("鏈表的數據爲:\n");
	while(p != head){			// 修改點5
 		printf("[%d]: %d \t", i, p->data);
 		i++;
 		p = p->next;
 		
 		if( (i%5) == 0)
 			printf("\n");
	}
	printf("\n");
} 


void Get_Mid_ListNode(LinkList head)
{
	LinkList end_p, mid_p;

	if(head->next == head){ 		// 修改點6
		printf("鏈表爲空\n");
		return; 
	}
		
	end_p = head;
	mid_p = head;
	
	while(end_p->next != head && end_p->next->next != head && end_p->next != NULL && end_p->next->next != NULL){ // 修改點7
		end_p = end_p->next->next;
		mid_p = mid_p->next;
	}
	printf("中間節點的值爲(%d) , 末尾中間節點的值爲(%d) \n", mid_p->data, end_p->data);
} 


void Insert_data(LinkList head)
{
	int i=0, max_len=0, num=0, data=0;
	LinkList p=head ,tmp_p;
	
	if(p->next == head){ 		// 修改點8
		printf("鏈表爲空\n");
		return; 
	}
	
	while( scanf("%d", &num) != 1 || num == 0){
		printf("\n當前輸入值非法,請輸入正確的數字\n\n");
		fflush(stdin);
	}
	
	max_len = Get_List_Len(head);
	if(num > max_len+1)
	{
		printf("插入節點位置不對(%d),長度超出範圍(%d)\n", num, max_len);
		return;	
	}
	// 開始在單鏈表中查找對應的位置 及 值 
	while( i != (num - 1)){
		i++;
		p = p->next;
		//printf("debug---i(%d) num-1(%d) data(%d)---\n", i,num-1,  p->data);
	}
	
	printf("插入節點位置的值爲 [%d]%d ,開始插入數據\n", i, p->data);
	while( scanf("%d", &data) != 1){
		printf("\n當前輸入值非法,請輸入正確的數據\n\n");
		fflush(stdin);
	}
	tmp_p = (LinkList)malloc(sizeof(ListNode));
	tmp_p->data = data;
	
	tmp_p->next = p->next;
	p->next = tmp_p;
	
	printf("插入數據完成\n");
} 

void Delete_data(LinkList head)
{
	int i=0, num=0, max_len=0;
	LinkList p=head->next , pre_p=head,tmp_p;
	
	if(p == head){ 
		printf("鏈表爲空\n");
		return; 
	}
	max_len = Get_List_Len(head);
	printf("您要刪除第幾個數據,當前數據長度爲%d\n", max_len);
	while(scanf("%d", &num) != 1 || num > max_len){
		printf("\n當前輸入值非法,請輸入正確的數據\n\n");
		fflush(stdin);
	}
	
	while(i != (num-1)){
		pre_p = p; 
		p = p->next;
		i++;
	}
	printf("要刪除的節點位置值爲 [%d]%d\n", i, p->data);
	tmp_p = p;
	pre_p->next = p->next;
	free(tmp_p);
}



int main(void)
{
	int cmd = 0;
	
	LinkList head;
	
	head = (LinkList)malloc(sizeof(ListNode));
	head->next = head;		// 修改點10
	
	while(1){
		printf(	"\n"
		    	"1.創建鏈表\n"
				"2.查看鏈表\n"
				"3.鏈表長度\n"
				"4.插入元素\n"
				"5.刪除指定元素\n"
				"6.中間節點數據\n"
				"7.刪除鏈表\n"
				"0.退出\n"
				"請輸入命令: ");
				
		while( scanf("%d", &cmd) != 1){
			printf("\n當前輸入非法,請輸入正確的命令\n\n");
			fflush(stdin);
		}
		
		printf("\n您輸入的命令爲 %d \n", cmd);

		// 檢查是否是退出操作 
		if(cmd == 0){ 
			printf("程序退出,謝謝!!! \n\n");
			break;
		} 
		 
		switch(cmd){
			case 1:		// 創建鏈表
				Create_List(head);
				break;
			case 2:		// 查看鏈表 
				Print_List(head);
				break;
			case 3:		// 鏈表長度 
				printf("\n鏈表長度爲 %d \n", Get_List_Len(head));
				break;
			case 4:		// 插入元素 
				Insert_data(head);
				break;
			case 5:		// 刪除元素 
				Delete_data(head);
				break;
			case 6:		// 中間節點數據 
				Get_Mid_ListNode(head);
				break;
			case 7:		// 刪除鏈表 
				Delete_List(head);
				break;
			default:
				printf("\n當前爲不支持的命令,請重新輸入正確的命令\n", cmd);
				break;
		}
		
		// 清空輸入輸出緩衝區 
		fflush(stdin); 
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章