線性表-數據結構

線性表有n(n>=0)個類型相同的數據節點組成的有限序列。數組

《a1,a2,a3.....an》函數

線性表是典型的的線性結構,表中數據元素有序且有限。
其特色可概括爲同一性,又窮性,有序性。指針

根據結構不一樣分爲 順序表,連接表 兩種。code

1.順序表:將同類型節點安邏輯順序一次存入一組連續的存儲單元中。blog

順序表的邏輯順序與物理順序一致,即,在物理內存中排列順序是相鄰連續的。內存

以一位數組爲例,其結構以下:get

| a1 | a2 | a3 | a4 | ......... | a(n-2) | a(n-1) | an |it

如下是順序表的使用:io

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
typedef int ElemType;
// 定義節點結構體
typedef struct
{
	ElemType elem[MAXSIZE];
	int last;
}SeqList;
// 初始化線性表
SeqList *InitList(  ) 
{  
  SeqList *p;
  p=(SeqList *)malloc(sizeof(SeqList));
  p->last = -1;
  return p;   
}
// 根據元素的值,獲取表中元素位置
int Locate(SeqList *L, ElemType e)
{ 
  int i;
  for (i=0;i<=L->last;i++)
      if (L->elem[i]==e) return i+1;
  return -1;
}
// 根據指定位置,獲取節點的值
ElemType GetData(SeqList *L,int i)
{
  if(i<=L->last+1) return L->elem[i-1];
  else printf("%d is wrong\n",i);
}

void main()
{ 
  int i;
  SeqList *p;
  p=InitList( );
  printf("%d\n",p->last);               //顯示-1 
  for(i=0;i<10;i++) p->elem[i]=i+50;    //50,51,52,53。。。59 
  p->last=i-1;                          //9寫入last,表示最後一個元素下標 
  i=Locate(p,53);                       //返回4 
  printf("%d\n",i);
  printf("%d\n",GetData(p,5));          //顯示54 
}

2.鏈表:用一組任意存儲單元,來存儲線性表中的數據元素。在物理內存中的位置沒有固定順序,可零散分佈在任意位置上。
每一個節點除存儲數據以外,還要存儲相鄰單元的地址信息。即:節點由 數據域 指針域兩部分組成。ast


從連接方式上可分爲:單鏈表、雙鏈表、環表
從實現角度上可分爲:動態鏈表、靜態鏈表

單鏈表:每一個節點的指針域只包含一個指針,第一個節點無前驅稱爲鏈表頭,整個鏈表經過鏈表頭獲取。最後一個節點無後驅,稱爲鏈表尾,指針域爲空。有些時候未使用方便,也會在第一個節點以前單獨掛一個頭結點,用於存放鏈表長度等數據,頭結點的next指針指向第一個節點。

單列表代碼演示:

#include "stdio.h"
#include "stdlib.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 
typedef int Status;
typedef int ElemType;
// 定義鏈表節點
typedef struct Node
{
    ElemType data;
    struct Node *next;
}Node;
// 初始化鏈表,爲鏈表頭分配空間
typedef struct Node *LinkList;
int InitList(LinkList *L)
{
    *L=(LinkList)malloc(sizeof(Node)); /* 產生頭結點,並使L指向此頭結點 */
    if(!(*L)) /* 存儲分配失敗 */
          return ERROR;
    (*L)->next=NULL; /* 指針域爲空 */
    return OK;
}

// 獲取鏈表長度
/* 初始條件:順序線性表L已存在。操做結果:返回L中數據元素個數 */
int ListLength(LinkList L)
{   int i=0;
    LinkList p=L->next; /* p指向第一個結點 */
    while(p)
    {
        i++;
        p=p->next;
    }
    return i;
}
void CreateFromTail(LinkList L)
{ Node *r, *s;
  char c;
  int  flag =1;   //設置一個標誌,當輸入"$"時,flag爲0,建表結束
  r=L;            //r指向鏈表的當前表尾,其初值指向頭結點
  while(flag)     //循環輸入表中元素值,將創建新結點s插入表尾*/
	{ c=getchar();
	  if(c!='$')
		{ s=(Node*)malloc(sizeof(Node));
		  s->data=c;
		  r->next=s;
		  r=s;	}
	  else
		{ flag=0;
		  r->next=NULL; //最後一個結點的next置爲空,表示鏈表結束
		}
	}   
} 
 
int main()
{
    LinkList L;
    int i;
    if(InitList(&L))  //指針的地址 
      printf("鏈表L初始化完畢,ListLength(L)=%d\n",ListLength(L));
    CreateFromTail(L);
    printf("鏈表L初始化完畢,ListLength(L)=%d\n",ListLength(L));

}

 

環表:是鏈表的首尾相接,尾巴節點的next指針指向頭指針,造成環狀順序結構

其操做與普通鏈表操做相似。

雙向鏈表:與單鏈表不一樣之處在與每一個節點指針域除了指向後驅節點的的next指針以外,還有指向前驅節點的prior節點。這樣方便雙向操做,可減小運算複雜度。

  (p->prior)->next == p == (p->next)->prior;

操做雙向鏈表代碼

#include <stdio.h>        //雙向非循環鏈表 
#include <stdlib.h>
#define ElemType int
#define ERROR -1
#define OK 1

typedef struct DNode
{ 
	ElemType data; 
	struct DNode  *prior,*next; 
}DNode,*DoubleList;

int DlinkIns(DoubleList L,int i,ElemType e)
{  
	DNode *s,*p;  		//在p結點以前插入s結點
   	int k;
   	p=L;  k=0;       	//從「頭」開始,查找第i個結點,至關於頭結點是0號結點
   	while(p->next!=L&&k<i) //找到尾節點沒找到跳出或k==i跳出
	{ p=p->next;
	  k=k+1; 
	}							     
   	if(p->next==L&&k!=i) //插入位置不合理,i的值不合適此鏈表
	{ printf("插入位置不合理!");
	  return ERROR;}
   	s=(DNode*)malloc(sizeof(DNode)); //p已就位,開始申請s結點空間   
	if (s) 				//s空間申請成功
	{
		s->data=e;
		p->prior->next=s;	//創建左邊關係
		s->prior=p->prior;
				
		p->prior=s;		//創建右邊關係
		s->next=p;	

		return OK;
	}
	else 	
		return ERROR;
}


void Init_DLinklist(DoubleList *H) 		//LinkList爲指針型
{ *H=(DoubleList)malloc(sizeof(DNode)); //申請一個結點空間
  (*H)->next=*H;                  
  (*H)->prior=*H; 
 }
void Creat_DLinkList(DoubleList L)
{   char c;
    static int i=1;
    DoubleList s;
    printf("請輸入第%d個結點的值",i);
    scanf("%d",&c);
    if(c!=-1){
    s=(DNode*)malloc(sizeof(DNode)); 
    s->data=c;
    L->next=s;
    s->prior=L;
    L->prior=s;
    s->next=L;
	}
    
    printf("請輸入第%d個結點的值",i+1);
	scanf("%d",&c);
	while(c!=-1)  			//輸入-1結束 
	 { 	DlinkIns(L,1,c); 	//在第一個結點以前插入,頭插法 
	 	i++;
	 	printf("請輸入第%d個結點的值",i+1);
	    scanf("%d",&c);
	 }
}
void Print_DLinkList(DoubleList L)
{  DoubleList p=L->next;
   while(p!=L) 
   {printf("%8d",p->data);
    p=p->next;
   }
	
}

int DlinkDel(DoubleList L,int i,ElemType *e)  //doublelinkdelete
{ 	DNode  *p;          //p指向要刪除的結點
  	int k;
  	p=L;  k=0;    //從「頭」開始,查找第i個結點,頭結點至關於第0個結點
  	while(p->next!=L && k<i) //找第i個結點
	{ p=p->next;
	  k=k+1; 
	}
  	if(p->next==L&&k<i)  return ERROR;  //到尾結點也未找到i結點,i太大
  	else	
  	{ 	
		*e=p->data;     //被刪除結點的值由e指針帶回給主調函數
		p->next->prior=p->prior;
		p->prior->next=p->next;
	
		free(p);
	}
}

int main(int argc, char *argv[]) {
	int i,e;
	DoubleList DL;
	Init_DLinklist(&DL);
	Creat_DLinkList(DL);
	Print_DLinkList(DL);
	printf("\n請輸入要刪除結點的序號:");
	scanf("%d",&i); 
	DlinkDel(DL,i,&e);
	Print_DLinkList(DL);
	printf("\n要刪除的結點的值爲:%d",e);
	return 0;
}
相關文章
相關標籤/搜索