1. 程式人生 > >資料結構---線性表之單鏈表(C語言)

資料結構---線性表之單鏈表(C語言)

上一篇已經寫過,線性表的儲存結構有順序儲存結構和鏈式儲存結構兩種,前者稱為順序表,後者稱為連結串列。本篇文章是對連結串列的學習。-------------------------------------------------------------------------------------------------------------------------連結串列:在連結串列儲存中,每個結點不僅包含所含元素的資訊,還包含元素之間邏輯關係的資訊。順序表與連結串列的比較:(1)順序表具有隨機訪問性,而連結串列不支援隨機訪問。(順序表是連續儲存的,只要知道開始的位置,就能找到任意一個位置的數,而連結串列中當前結點的位置是由其前驅結點中的地址資訊所指示的,而不是由其相對於初始位置的偏移量來確定的)(2)順序表佔用連續的儲存空間,連結串列的結點可以散落在記憶體中的任意位置,不需要一次性劃分所有結點所需的空間連結串列,支援儲存空間的動態分配。(3)連結串列中的每一個結點需要劃出一部分空間來儲存指向下一個結點位置的指標,因此連結串列中結點的儲存空間利用率較順序表稍微低一些。--------------------------------------------------------------------------------------------------------------------------單鏈表是長這個樣子滴!
下面這個是單鏈表的結點結構圖---------------------------------------------------------------------------------------------------------------------------
還是直接上程式碼!(1)單鏈表結點定義
typedef struct
{
int data;
struct LNode *next;
}LinkList;
(2)輸入資料存入陣列a
 int n;int a[maxSize]; //這四個量要設定成全域性變數,因為這兩個量在多個函式中都要用到 LinkList *head;     //頭指標LinkList *L;
void InData( )
{ 
 printf("請輸入您要存入資料的個數:");
 scanf_s("%d", &n);
 if (n >= 0 && n < maxSize)
 {
  printf("請輸入資料:");
  for (int i = 0; i < n; i++)
  {
   scanf_s("%d", &a[i]);
  }
  printf("您所輸入的資料為:");
  for (int j = 0; j < n; j++)
  {
   printf("%d  ", a[j]);
  }
 }
 else
 {
  printf("不在區間內!請重新選定數值!");
 }

(3)尾插法建立連結串列(有頭結點)
int CreateList1(LinkList *L)
{ 
InData(); 
LinkList *s,*r;  //s用來指向新申請的結點,r用來指向連結串列L的終端結點 
L = (LinkList*)malloc(sizeof(LinkList));  //申請L的頭結點空間
head = (LinkList*)malloc(sizeof(LinkList)); 
L->next = NULL;  //初始化 
r = L;   //r指向頭結點,此時的頭結點就是終端結點
head = L;  //非常重要!!!得到連結串列的頭指標,以便在之後的函式中找到連結串列呼叫
for (int i = 0; i <n; i++) 
{ 
   s = (LinkList*)malloc(sizeof(LinkList));  //s指向新申請的結點 
   s->data = a[i];  
   r->next = s;  //用r來接納新結點  
   r = r->next;  //r指向終端結點,以便於接納下一個結點的到來 
 } 
 r->next = NULL;  //陣列a中所有的元素都已經裝入連結串列L中,L的終端結點指標域設定為NULL,L就建立完成了 
 printf("\n連結串列中的資料為:");
 LinkList *p = L->next; 
 for (int j = 0; j < n; j++)
 {  
   printf("%d  ",p->data);  
  p = p->next; 
 } 
return L;
}

結果如圖所示:(4)頭插法建立連結串列(有頭結點)
void CreateList2(LinkList *L)
{
 InData();
 LinkList *s;
 int i;
 L = (LinkList*)malloc(sizeof(LinkList));
 L->next = NULL;
 head = (LinkList*)malloc(sizeof(LinkList));
 head = L;
 for (i = 0; i < n; i++)
 {
  s= (LinkList*)malloc(sizeof(LinkList));
  s->data = a[i];
  s->next = L->next;  //s所指向的新節點的指標域指向L的開始結點
  L->next = s;  //頭結點的指標域指向s結點,使得s成為新的開始結點
 }
 printf("\n連結串列中的資料為:");
 LinkList *p = L->next;
 for (int j = 0; j < n; j++)
 {
  printf("%d  ", p->data);
  p = p->next;
 }
 return L;
}
結果如下圖所示:(5)在指定位置後面插入連結串列步驟1:先讓S結點指向p之後的結點步驟2:切斷p和p後面的那個結點的關係步驟3:讓p結點的指標域指向S結點
int InsertNode()
{
	LinkList *s,*r;
	s = (LinkList*)malloc(sizeof(LinkList));
	r = (LinkList*)malloc(sizeof(LinkList));
	r = head;                 //r此時和頭指標一樣指向連結串列的頭結點處
	int x, e;
	printf("\n請輸入您想插入資料的位置:");
	scanf_s("%d", &x);
	if (x<0 || x>n)
	{
		printf("\n區間錯誤");
	}
	else
	{
		printf("\n請輸入資料:");
		scanf_s("%d", &e);
		s->data = e;
	}

	for (int i = 0; i < x; i++)
		head = head->next;

	s->next = head->next;  //插入最關鍵的兩步
	head->next = s;
	n++;                  //連結串列長度增加
	printf("\n資料為:");
	for (int j = 0; j < n; j++)
	{
		r = r->next;
		printf("%d  ", r->data);
	}
	return L;
}

void main()
{
	CreateList2(&L);
	InsertNode();
	system("pause");
}
結果如下圖:(6)刪除指定位置的結點
步驟1:宣告一個指標p指向連結串列頭結點,向後遍歷p=p->next,找到要刪除的結點的位置步驟2:要刪除的結點q=p->next步驟3:p->next=q->next步驟4:釋放記憶體 free(q)
int DeleteNode()
{
	LinkList *q,*p;
	int x;
	q = (LinkList*)malloc(sizeof(LinkList));
	p = (LinkList*)malloc(sizeof(LinkList));
	p = head;
	printf("\n請輸入您想刪除的結點的位置:");
	scanf_s("%d", &x);
	if (x<0 || x>n)
	{
		printf("不在區間內!");
	}
	for (int i = 0; i < x; i++)
	{
		head = head->next;
	}
	q = head->next;
	head->next = q->next;
	n--;
	printf("\n資料為:");
	for (int j = 0; j < n; j++)
	{
		p = p->next;
		printf("%d  ", p->data);
	}
	return L;
}

void main()
{
	CreateList1(&L);
	//InsertNode();
	DeleteNode();
	system("pause");
}