1.順序表的定義
順序表是線性表的順序表示,即用一組地址連續的存儲單元依次存儲線性表的數據元素。
2.順序表的存儲結構
為了使順序表的空間分配盡可能不受限制,這里先讓順序表的初始化容量為8,當空間不足時再對容量進行擴展,每次容量的增量為3。
#define SEQLIST_INIT_SIZE 8 //初始化大小 #define INC_SIZE 3 //空間的增量 typedef int ElemType; //元素類型 typedef struct SeqList { ElemType *base; //指向順序表開辟的基准空間 int capacity; //容量 int size; //表的長度(大小) }SeqList;
3.順序表的常用操作
1.初始化
//順序表的初始化 void InitSeqList(SeqList *list) { list->base = (ElemType *)malloc(sizeof(ElemType) * SEQLIST_INIT_SIZE); assert(list->base != NULL); list->capacity = SEQLIST_INIT_SIZE; list->size = 0; }
2.容量擴展
//空間不足,重新開辟 bool Inc(SeqList *list) { ElemType *newbase = (ElemType*)realloc(list->base,sizeof(ElemType)*(list->capacity+INC_SIZE)); //空間開辟是否失敗? if(newbase == NULL) { printf("增配空間失敗,內存不足.\n"); return false; } list->base = newbase; list->capacity += INC_SIZE; return true; }
3.尾插
//在順序表尾部插入數據 void push_back(SeqList *list, ElemType x) { //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能尾部插入數據.\n",x); return; } //數據尾插 list->base[list->size] = x; //size的大小就是尾部插入時數組的下標 list->size++; }
4.頭插
//在順序表頭部插入數據 void push_front(SeqList *list, ElemType x) { //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能頭部插入數據.\n",x); return; } //將順序表數據后移 for(int i=list->size; i>0; --i) { list->base[i] = list->base[i-1]; } //數據頭插 list->base[0] = x; list->size++; }
5.存儲數據顯示
//顯示順序表內的數據 void show_list(SeqList *list) { for(int i=0; i<list->size; ++i) { printf("%d ",list->base[i]); } printf("\n"); }
6.尾刪
//刪除順序表尾部數據 void pop_back(SeqList *list) { //判斷順序表是否為空? if(list->size == 0) { printf("順序表已空,不能尾部刪除數據.\n"); return; } //將size值減1,來達到刪除的目的 list->size--; }
7.頭刪
//刪除順序表頭部數據 void pop_front(SeqList *list) { //判斷表是否為空? if(list->size == 0) { printf("順序表已空,不能尾部刪除數據.\n"); return; } //將順序表中的數據前移一位(第一個數據除外) for(int i=0; i<list->size-1; ++i) { list->base[i] = list->base[i+1]; } //將size值減1,來達到刪除的目的 list->size--; }
8.按位置插入數據
//按位置插入數據 void insert_pos(SeqList *list, int pos, ElemType x) { //判斷位置是否合法? if(pos<0 || pos>list->size) { printf("插入數據的位置非法,不能插入數據.\n"); return; } //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能按位置插入數據.\n",x); return; } //將該位置及其之后的數據都向后移動一位 for(int i=list->size; i>pos; --i) { list->base[i] = list->base[i-1]; } //將數據插入 list->base[pos] = x; list->size++; }
9.查找數據
假定順序表內的數據唯一。
//查找數據 int find(SeqList *list, ElemType key) { //遍歷順序表,查找數據 for(int i=0; i<list->size; ++i) { if(list->base[i] == key) return i; //找到數據返回 } return -1; }
10.求順序表長度
//求順序表的長度 int length(SeqList *list) { return list->size; }
11.按位置刪除數據
//按位置刪除數據 void delete_pos(SeqList *list, int pos) { //判斷位置是否合法? if(pos<0 || pos>=list->size) { printf("刪除數據的位置非法,不能刪除數據.\n"); return; } //將該位置之后的數據都向前移動一位 for(int i=pos; i<list->size-1; ++i) { list->base[i] = list->base[i+1]; } list->size--; }
12.按值刪除數據
//按值刪除 void delete_val(SeqList *list, ElemType key) { //查找值所在的位置 int pos = find(list,key); //順序表中是否存在該值? if(pos == -1) { printf("要刪除的數據不存在.\n"); return; } //存在該值就刪除 delete_pos(list,pos); }
13.排序
//順序表的排序(冒泡排序 ) void sort(SeqList *list) { //冒泡排序,每趟比較可以確定一個最大(最小)的數,所以需要size-1趟(最后一次自己跟自己比較不需要) for(int i=0; i<list->size-1; ++i) { //每趟中需要比較size-i-1次(前面比較完的i個數不需要重復比較,最后一次自己跟自己比較不需要) for(int j=0; j<list->size-i-1; ++j) { if(list->base[j] > list->base[j+1]) { ElemType tmp = list->base[j]; list->base[j] = list->base[j+1]; list->base[j+1] = tmp; } } } }
14.逆置
//順序表的逆置 void resver(SeqList *list) { //判斷是否需要進行逆置操作 if(list->size==0 || list->size==1) return; //low低位指針,指向低位 int low = 0; //hight高位指針,指向高位 int high = list->size-1; //臨時空間 ElemType tmp; //當低位指針所指位置小於高位指針指向位置時,進行數據交換 while(low < high) { tmp = list->base[low]; list->base[low] = list->base[high]; list->base[high] = tmp; low++; high--; } }
15.清空順序表
//清空順序表 void clear(SeqList *list) { list->size = 0; }
16.銷毀順序表
//銷毀順序表 void destroy(SeqList *list) { free(list->base); list->base = NULL; list->capacity = 0; list->size = 0; }
4.擴展
將兩個從小到大排序的有序表按照由小到大的順序合並到另一個有序表中。
//將兩個從小到大排序的有序表按照由小到大的順序合並到另一個有序表中 void merge(SeqList *lt, SeqList *la, SeqList *lb) { //構造存放有序表la和lb的有序表lt lt->capacity = la->size + lb->size; lt->base = (ElemType*)malloc(sizeof(ElemType)*lt->capacity); assert(lt->base != NULL); int ia = 0; int ib = 0; int ic = 0; //當有序表la和lb中的元素都還沒比較完時,將它們相應下標下的元素進行比較,並將小的元素放入lt while(ia<la->size && ib<lb->size) { if(la->base[ia] < lb->base[ib]) lt->base[ic++] = la->base[ia++]; else lt->base[ic++] = lb->base[ib++]; } //當只有有序表la中有元素時,將la中的剩余元素逐一放入lt while(ia < la->size) { lt->base[ic++] = la->base[ia++]; } //當只有有序表lb中有元素時,將lb中的剩余元素逐一放入lt while(ib < lb->size) { lt->base[ic++] = lb->base[ib++]; } //更新有序表lt的長度 lt->size = la->size + lb->size; }
5.附錄
Main.cpp

#include"SeqList.h" //順序表常用操作測試 void main() { SeqList mylist; InitSeqList(&mylist); ElemType Item; int pos; int select = 1; while(select) { printf("**************************************\n"); printf("* [1] push_back [2] push_fornt *\n"); printf("* [3] show_list [4] pop_back *\n"); printf("* [5] pop_front [6] insert_pos *\n"); printf("* [7] find [8] lenght *\n"); printf("* [9] delete_pos [10] delete_val *\n"); printf("* [11] sort [12] resver *\n"); printf("* [13] clear [14*] destroy *\n"); printf("* [0] quit_system *\n"); printf("**************************************\n"); printf("請選擇:>"); scanf("%d",&select); if(select == 0) break; switch(select) { case 1: printf("請輸入要插入的數據(-1結束):>"); while(scanf("%d",&Item),Item!=-1) { push_back(&mylist,Item); } break; case 2: printf("請輸入要插入的數據(-1結束):>"); while(scanf("%d",&Item),Item!=-1) { push_front(&mylist,Item); } break; case 3: show_list(&mylist); break; case 4: pop_back(&mylist); break; case 5: pop_front(&mylist); break; case 6: printf("請輸入要插入數據:>"); scanf("%d",&Item); printf("請輸入要插入的位置:>"); scanf("%d",&pos); insert_pos(&mylist,pos,Item); break; case 7: printf("請輸入要查找的數據:>"); scanf("%d",&Item); pos = find(&mylist,Item); if(pos == -1) printf("查找的數據%d在順序表中不存在.\n",Item); else printf("查找的數據%d在順序表中的%d下標位置.\n",Item,pos); break; case 8: printf("順序表的長度為:> %d\n",length(&mylist)); break; case 9: printf("請輸入要刪除數據的位置:>"); scanf("%d",&pos); delete_pos(&mylist,pos); break; case 10: printf("請輸入要刪除的數據:>"); scanf("%d",&Item); delete_val(&mylist,Item); break; case 11: sort(&mylist); break; case 12: resver(&mylist); break; case 13: clear(&mylist); break; //case 14: //destroy(&mylist); // break; default: printf("輸入的選擇錯誤,請重新輸入.\n"); break; } } destroy(&mylist); } /* //擴展測試 void main() { SeqList mylist,youlist,list; InitSeqList(&mylist); InitSeqList(&youlist); push_back(&mylist,1); push_back(&mylist,3); push_back(&mylist,5); push_back(&mylist,7); push_back(&mylist,9); push_back(&youlist,2); push_back(&youlist,4); //push_back(&youlist,6); push_back(&youlist,8); //push_back(&youlist,10); merge(&list,&mylist,&youlist); show_list(&list); } */
SeqList.h

#ifndef __SEQLIST_H__ #define __SEQLIST_H__ #include<stdio.h> #include<malloc.h> #include<assert.h> #define SEQLIST_INIT_SIZE 8 //初始化大小 #define INC_SIZE 3 //空間的增量 typedef int ElemType; //元素類型 typedef struct SeqList { ElemType *base; //指向順序表開辟的基准空間 int capacity; //容量 int size; //表的長度(大小) }SeqList; bool Inc(SeqList *list); void InitSeqList(SeqList *list); void push_back(SeqList *list, ElemType x); void push_front(SeqList *list, ElemType x); void show_list(SeqList *list); void pop_back(SeqList *list); void pop_front(SeqList *list); void insert_pos(SeqList *list, int pos, ElemType x); int find(SeqList *list, ElemType key); int length(SeqList *list); void delete_pos(SeqList *list, int pos); void delete_val(SeqList *list, ElemType key); void sort(SeqList *list); void resver(SeqList *list); void clear(SeqList *list); void destroy(SeqList *list); void merge(SeqList *lt, SeqList *la, SeqList *lb); #endif //__SEQLIST_H__
SeqList.cpp

#include"SeqList.h" //空間不足,重新開辟 bool Inc(SeqList *list) { ElemType *newbase = (ElemType*)realloc(list->base,sizeof(ElemType)*(list->capacity+INC_SIZE)); //空間開辟是否失敗? if(newbase == NULL) { printf("增配空間失敗,內存不足.\n"); return false; } list->base = newbase; list->capacity += INC_SIZE; return true; } //順序表的初始化 void InitSeqList(SeqList *list) { list->base = (ElemType *)malloc(sizeof(ElemType) * SEQLIST_INIT_SIZE); assert(list->base != NULL); list->capacity = SEQLIST_INIT_SIZE; list->size = 0; } //在順序表尾部插入數據 void push_back(SeqList *list, ElemType x) { //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能尾部插入數據.\n",x); return; } //數據尾插 list->base[list->size] = x; //size的大小就是尾部插入時數組的下標 list->size++; } //在順序表頭部插入數據 void push_front(SeqList *list, ElemType x) { //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能頭部插入數據.\n",x); return; } //將順序表數據后移 for(int i=list->size; i>0; --i) { list->base[i] = list->base[i-1]; } //數據頭插 list->base[0] = x; list->size++; } //顯示順序表內的數據 void show_list(SeqList *list) { for(int i=0; i<list->size; ++i) { printf("%d ",list->base[i]); } printf("\n"); } //刪除順序表尾部數據 void pop_back(SeqList *list) { //判斷順序表是否為空? if(list->size == 0) { printf("順序表已空,不能尾部刪除數據.\n"); return; } //將size值減1,來達到刪除的目的 list->size--; } //刪除順序表頭部數據 void pop_front(SeqList *list) { //判斷表是否為空? if(list->size == 0) { printf("順序表已空,不能尾部刪除數據.\n"); return; } //將順序表中的數據前移一位(第一個數據除外) for(int i=0; i<list->size-1; ++i) { list->base[i] = list->base[i+1]; } //將size值減1,來達到刪除的目的 list->size--; } //按位置插入數據 void insert_pos(SeqList *list, int pos, ElemType x) { //判斷位置是否合法? if(pos<0 || pos>list->size) { printf("插入數據的位置非法,不能插入數據.\n"); return; } //判斷順序表空間是否滿且增加空間是否失敗? if(list->size >= list->capacity && !Inc(list)) { printf("順序表空間已滿,%d不能按位置插入數據.\n",x); return; } //將該位置及其之后的數據都向后移動一位 for(int i=list->size; i>pos; --i) { list->base[i] = list->base[i-1]; } //將數據插入 list->base[pos] = x; list->size++; } //查找數據 int find(SeqList *list, ElemType key) { //遍歷順序表,查找數據 for(int i=0; i<list->size; ++i) { if(list->base[i] == key) return i; //找到數據返回 } return -1; } //求順序表的長度 int length(SeqList *list) { return list->size; } //按位置刪除數據 void delete_pos(SeqList *list, int pos) { //判斷位置是否合法? if(pos<0 || pos>=list->size) { printf("刪除數據的位置非法,不能刪除數據.\n"); return; } //將該位置之后的數據都向前移動一位 for(int i=pos; i<list->size-1; ++i) { list->base[i] = list->base[i+1]; } list->size--; } //按值刪除 void delete_val(SeqList *list, ElemType key) { //查找值所在的位置 int pos = find(list,key); //順序表中是否存在該值? if(pos == -1) { printf("要刪除的數據不存在.\n"); return; } //存在該值就刪除 delete_pos(list,pos); } //順序表的排序(冒泡排序 ) void sort(SeqList *list) { //冒泡排序,每趟比較可以確定一個最大(最小)的數,所以需要size-1趟(最后一次自己跟自己比較不需要) for(int i=0; i<list->size-1; ++i) { //每趟中需要比較size-i-1次(前面比較完的i個數不需要重復比較,最后一次自己跟自己比較不需要) for(int j=0; j<list->size-i-1; ++j) { if(list->base[j] > list->base[j+1]) { ElemType tmp = list->base[j]; list->base[j] = list->base[j+1]; list->base[j+1] = tmp; } } } } //順序表的逆置 void resver(SeqList *list) { //判斷是否需要進行逆置操作 if(list->size==0 || list->size==1) return; //low低位指針,指向低位 int low = 0; //hight高位指針,指向高位 int high = list->size-1; //臨時空間 ElemType tmp; //當低位指針所指位置小於高位指針指向位置時,進行數據交換 while(low < high) { tmp = list->base[low]; list->base[low] = list->base[high]; list->base[high] = tmp; low++; high--; } } //清空順序表 void clear(SeqList *list) { list->size = 0; } //銷毀順序表 void destroy(SeqList *list) { free(list->base); list->base = NULL; list->capacity = 0; list->size = 0; } //將兩個從小到大排序的有序表按照由小到大的順序合並到另一個有序表中 void merge(SeqList *lt, SeqList *la, SeqList *lb) { //構造存放有序表la和lb的有序表lt lt->capacity = la->size + lb->size; lt->base = (ElemType*)malloc(sizeof(ElemType)*lt->capacity); assert(lt->base != NULL); int ia = 0; int ib = 0; int ic = 0; //當有序表la和lb中的元素都還沒比較完時,將它們相應下標下的元素進行比較,並將小的元素放入lt while(ia<la->size && ib<lb->size) { if(la->base[ia] < lb->base[ib]) lt->base[ic++] = la->base[ia++]; else lt->base[ic++] = lb->base[ib++]; } //當只有有序表la中有元素時,將la中的剩余元素逐一放入lt while(ia < la->size) { lt->base[ic++] = la->base[ia++]; } //當只有有序表lb中有元素時,將lb中的剩余元素逐一放入lt while(ib < lb->size) { lt->base[ic++] = lb->base[ib++]; } //更新有序表lt的長度 lt->size = la->size + lb->size; }