資料結構----線性表的使用(c)
阿新 • • 發佈:2018-12-13
PS:在學習資料結構之前,我相信很多博友也都學習過一些語言,比如說java,c語言,c++,web等,我們之前用的一些方法大都是封裝好的,就java而言,裡面使用了大量的封裝好的方法,一些演算法也大都寫好了,java還有三個特性,封裝、繼承、多型。當然這裡不是講Java,這裡主要是說內部結構,大家都知道資料結構有些東西是分為邏輯結構和物理結構的,物理結構有分為順序結構和鏈式結構,有不懂得可以百度百科,這裡主要是分享線性表的順序結構。那麼什麼是線性表呢,線性表是最基本、最簡單、也是最常用的一種資料結構。線性表(linear list)是資料結構的一種,一個線性表是n個具有相同特性的資料元素的有限序列。
線性表
- 順序表
- 鏈式表
1:順序表分析
- 結構體建立
- 初始化順序表
- 插入操作
- 刪除操作
- 查詢操作
- 修改操作
由於順序表比較簡單,這裡解釋都在程式碼中,在外就不在贅述。
1-1:結構體的建立
#define ElemType int #define MAXSIZE 100 //定義變數不需要分號。 //建立線性表 typedef struct { ElemType elem[MAXSIZE]; int length; //長度 } SqList;
1-2:初始化順序表
int InitList(SqList &L) {// 初始化表,一個空表。 L.length = 0; return 0; }
1-3:操作方法
/** * @descibe 插入元素 * @param L 線性表 * @param pos 所在位置(並非角標) * @param data 插入元素 * */ int ListInsert(SqList &L, int pos, ElemType data) { if (pos < 1 || pos > L.length + 1) { printf("插入的不合法"); return -1; } inti; //在插入的同時,i要保證在pos以及pos後方,入1,2,3,4,5當在第3個插入時,須把原有的第三個資料以及以後資料後移一位,空出第三個位置。 for (i = L.length; i >= pos; i--) { L.elem[i] = L.elem[i - 1]; } L.elem[pos - 1] = data; L.length++; return 0;// } /** * 線性表中刪除操作 * @param L 線性表 * @param pos 所在位置(並非角標) * @param data 插入元素 * */ int ListDelete(SqList &L, int pos, int data) { if (pos < 1 || pos > L.length) { printf("刪除角標不合法"); return -1; } if (!(L.elem[pos - 1] == data)) { printf("沒有這個數字"); return -1; } int i; //在插入的同時,i要保證在pos以及pos後方,入1,2,3,4,5當在第3個插入時,須把原有的第三個資料以及以後資料後移一位,空出第三個位置。 for (i = pos; i <= L.length; i++) { L.elem[i - 1] = L.elem[i]; } L.length--; return 0;//返回0表示成功; } //查詢資料 int queryList(SqList L, int e) { //如果小於1證明沒有資料,則直接返回。 if (L.length < 1) { printf("表中沒有資料"); return -1; } for (int i = 0; i < L.length; i++) { if (L.elem[i] == e) { printf("找到該資料:%d角標為:%d \n", L.elem[i], i); } } return 0; } //修改資料 int xiugai(SqList &L, int pos, int e) { if (pos < 1 || pos > L.length) { printf("修改角標不合法"); return -1; } L.elem[pos - 1] = e; return 0; } //列印全部資料 void PrintF(SqList L) { printf("打印表中所有元素\n"); int i; for (i = 0; i < L.length; i++) { printf("%d\n", L.elem[i]); } }
綜上所述:線性表和之前的陣列類似,很容易理解。在使用的過程記得宣告一下方法(函式);
2:連結串列分析
- 結構體建立
- 初始化順序表
- 插入操作
- 刪除操作
- 查詢操作
- 修改操作
需要注意的是這裡的結構體需要一個指標,前一個結點的指標指向下一個結點,依次類推,最後一個指標指向NULL;
2-1:結構體建立
/** * @describe 建立一個結構體 * SLink *next指標; * *SLinkListL 建立一個結構體指標 * */ typedef struct SLink { int data; struct SLink *next; } SLink, *SLinkListL;
2-2:初始化連結串列
/** * @describe 初始化連結串列 * */ SLinkListL initLinkL() { //1:分配一個空間 SLinkListL sLinkListL = (SLinkListL) malloc(sizeof(SLink)); //2:判斷是否建立成功 if (!sLinkListL) { exit(-1); } sLinkListL->next = NULL; printf("初始化單鏈表成功\n"); return sLinkListL; }
2-3:操作--增刪該查
這裡需要注意的是修改這個操作,找p的時候要找到要修改的p,而不是前一個結點,比如說,咱們在第二個位置插入的時候要找到第一個位置作為p,二修改的時候就要找到第二個位置,也就是說pos傳值的時候不用減一。
/** * @describe 插入操作 * * @param L 連結串列型別 * @param pos 插入位置 * @param e 插入元素 * */ int insertLinkL(SLinkListL &L, int pos, int e) { SLinkListL p = L; //判斷是否符合連結串列的長度; int i = 0; //判斷長度,尋找要插入的位置(前一位); while (p && i < pos-1) { p = p->next; i++; } //判斷長度是否超過pos if (!p || i > pos-1) { return 0; } //為新元素建立結點(分配空間) SLinkListL s = (SLinkListL) malloc(sizeof(SLink)); s->data = e; s->next = p->next; p->next = s; return 1; } /** * @describe 刪除操作 * @param L 連結串列型別 * @param pos 刪除位置 * @param e 刪除存放元素 * */ int deleteLinkL(SLinkListL &L, int pos, int *e) { SLinkListL p = L; //1:判斷位置 int i = 0; while (p && i < pos-1) { p = p->next; i++; } if (!p || i > pos-1) { printf("刪除位置不合法\n"); return -1; } //定義一個空的變數,用於存放p的指標,入a1,a2,a3,如果要刪除a2,則p指向a1,此時,把a1的next先交給s(暫存,此時代表a2(因為a1的指標是指向a2)),然後用s去取下一個指標(next)就是a3, SLinkListL s;//s為了釋放掉刪除元素的空間 s = p->next; p->next = s->next; *e = s->data;//暫存 free(s); printf("刪除成功\n"); return 0; } /** * @describe 查詢操作 * @param L:連結串列型別 * @param e:e查詢元素 * */ int queryLinkL(SLinkListL L, int e) { printf("查詢元素為:%d",e); SLinkListL p = L; int i = 1; while (p) { p = p->next; if (p->data == e) { printf("找到元素%d\n", i); return 0; } i++; } printf("下標不合法/沒有找到該資料"); return -1; } /** * @describe 修改操作 * @param L:連結串列型別 * @param i:修改元素的位置 * @param e:修改元素值 * */ int updataLinkL(SLinkListL &L, int pos, int e) { printf("修改資料為第:%d 個,值為:%d\n",pos,e); SLinkListL p = L; int i = 0; while (p && i < pos) { p = p->next; i++; } if (!p || i > pos) { printf("修改失敗--原因:修改的下標越界\n"); return -1; } p->data = e; printf("修改成功\n"); return 0; } void printLL(SLinkListL L) { printf("列印全部資料\n"); SLinkListL p = L->next; while (p) { printf("%d ", p->data); p = p->next; } printf("\n"); }
綜上所述:只多了一個指標,一開始看估計還有有看不懂的地方,按照順序把程式碼貼上到你編輯器上,執行起來慢慢看。