在顺序表中,每个结点的存储地址是该结点在表中的位置的线性函数,是一种随机存取结构。顺序表是用向量实现的线性表,向量的下标可以看作结点的相对地址。因此顺序表的的特点是逻辑上相邻的结点其物理位置亦相邻。下面对顺序表进行头插、头删、尾插、尾删、指定位置插入数据、查找数据位置、删除某一个数、折半查找、冒泡排序和选择排序等操作并进行测试。
头函数:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<assert.h> #define MAX_SIZE 100 typedef int DataType; typedef struct SeqList { DataType arry[MAX_SIZE]; size_t size; }SeqList;
各函数的编写:
#include"SeqList.h" void PrintSeqList(SeqList* pSeq) { assert(pSeq); if (pSeq->size > 0 && pSeq->size <= MAX_SIZE) { for (int begin = 0; begin < (int)pSeq->size; begin++) { printf("%d ", pSeq->arry[begin]); } } else { printf("SeqList is Empty!"); return; } } void InitSeqList(SeqList* pSeq) { assert(pSeq); pSeq->size = 0; for (int begin = 0; begin < (int)pSeq->size; begin++) { pSeq->arry[begin] = 0; } } void PushBack(SeqList* pSeq, DataType x)//尾插 { assert(pSeq); if (pSeq->size >= MAX_SIZE) { printf("SeqList is Full!"); return; } else { pSeq->arry[pSeq->size] = x; ++pSeq->size; } } void PopBack(SeqList* pSeq)//尾删 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } else { pSeq->arry[pSeq->size] = 0; --pSeq->size; } } void PushFront(SeqList* pSeq, DataType x)//头插 { assert(pSeq); if (pSeq->size >= MAX_SIZE) { printf("SeqList is Full!"); return; } else { for (int i = pSeq->size; i > 0; i--) {//第一位数以后的数从后往前依次后移一位 pSeq->arry[i] = pSeq->arry[i - 1]; } pSeq->arry[0] = x;//第一位插入x ++pSeq->size; } } void PopFront(SeqList* pSeq)//头删 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } else { for (int i = 0; i < (int)pSeq->size - 1; i++) {//第一位以后的数从前向后依次前移一位 pSeq->arry[i] = pSeq->arry[i + 1]; } --pSeq->size; } } void Insert(SeqList* pSeq, size_t pos, DataType x)//在指定位置处插入一个数 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } else if (pSeq->size < pos || pos<0) { printf("Position is not exist!"); return; } else { for (int i = (int)pSeq->size; i > (int)pos - 1; i--) {//第pos-1位以后的数从后往前依次后移一位 pSeq->arry[i] = pSeq->arry[i - 1]; } pSeq->arry[pos - 1] = x;//第pos位插入x ++pSeq->size; } } int Find(SeqList* pSeq, DataType x)//查找指定数的位置 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return -1; } else { for (int i = 0; i < (int)pSeq->size; i++) { if (pSeq->arry[i] == x) return i + 1; } printf("x is not exist!"); return -1; } } void Erase(SeqList* pSeq, size_t pos)//删除某位的值 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } else if (pSeq->size < pos || pos<0) { printf("Position is not exist!"); return; } else { for (int i = (int)pos - 1; i < (int)pSeq->size - 1; i++) {//第pos位以后的数从前向后依次前移一位 pSeq->arry[i] = pSeq->arry[i + 1]; } --pSeq->size; } } void Remove(SeqList* pSeq, DataType x)//删除某数 { assert(pSeq); if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } int pos = Find(pSeq, x); Erase(pSeq, pos); } void RemoveAll(SeqList* pSeq, DataType x)//删除所有x { assert(pSeq); int count = 0; if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } for (int i = 0; i < (int)pSeq->size; i++) { //1 2 3 4 3 5 3 //如果删除所有3,当遇到一个3时,count++;其后面的数依次前移count位 if (pSeq->arry[i] == x) count++; else pSeq->arry[i - count] = pSeq->arry[i]; } pSeq->size -= count; } void swap(int* num1, int* num2) { assert(num1); assert(num2); int temp = *num1; *num1 = *num2; *num2 = temp; } void BubbleSort(SeqList* pSeq)//冒泡排序 { assert(pSeq); int flag;//冒泡排序的优化:定义一个标志位flag,接近有序时停止冒泡 if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } for (int j = 0; j < (int)pSeq->size - 1; j++)//排序pSeq->size - 1趟 { for (int i = 0; i < (int)pSeq->size - j - 1; i++)//每一趟冒泡出一个最大数 { flag = 0; if (pSeq->arry[i] > pSeq->arry[i + 1]) { flag = 1; swap(&pSeq->arry[i], &pSeq->arry[i + 1]); } if (flag = 0) return; } } } //选择排序的优化:一次选出最大最小的数据分别放在序列的两端 void SeclectSort(SeqList* pSeq) { assert(pSeq); int i, j, min, max; int len = pSeq->size - 1; if (pSeq->size <= 0) { printf("SeqList is Empty!"); return; } for (i = 0; i < (int)pSeq->size - 1; i++, len--) { min = 0; max = len; for (j = i; j <= max; j++) {//比较第i个元素和其后的元素找到最小的和最大的 if (pSeq->arry[j] < pSeq->arry[min]) swap(&pSeq->arry[j], &pSeq->arry[min]); if (pSeq->arry[j] > pSeq->arry[max]) swap(&pSeq->arry[j], &pSeq->arry[max]); } } } int BinarySearch(SeqList* pSeq, DataType x)//折半查找 { assert(pSeq); int left = 0; int right = pSeq->size;//此法为左闭右开区间 //int right = pSeq->size - 1;此法为左闭右闭区间 if (pSeq->size <= 0) { printf("SeqList is Empty!"); return -1; } while (left < right) //while (left <= right) { int mid = left + (right - left) / 2; if (pSeq->arry[mid] < x) left = mid + 1; else if (pSeq->arry[mid] > x) right = mid; //right = mid - 1; else return mid + 1; } return -1; }
主函数中对各函数进行测试用例:
#include"SeqList.h" void PrintSeqList(SeqList* pSeq); void InitSeqList(SeqList* pSeq); void PushBack(SeqList* pSeq, DataType x); void PopBack(SeqList* pSeq); void PushFront(SeqList* pSeq, DataType x); void PopFront(SeqList* pSeq); void Insert(SeqList* pSeq, size_t pos, DataType x); int Find(SeqList* pSeq,DataType x); void Erase(SeqList* pSeq, size_t pos);//删除某位的值 void Remove(SeqList* pSeq, DataType x);//删除某数 void RemoveAll(SeqList* pSeq, DataType x);//删除所有x void BubbleSort(SeqList* pSeq); //冒泡排序的优化:一次选出最大最小的数据分别放在序列的两端 void SeclectSort(SeqList* pSeq); int BinarySearch(SeqList* pSeq, DataType x); void Test1() {//尾插尾删 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PrintSeqList(&seq); PopBack(&seq); PopBack(&seq); printf("\n---------------\n"); PrintSeqList(&seq); PopBack(&seq); PopBack(&seq); printf("\n---------------\n"); PopBack(&seq); printf("\n---------------\n"); PrintSeqList(&seq); } void Test2() {//头插头删 SeqList seq; InitSeqList(&seq); PushFront(&seq, 1); PushFront(&seq, 2); PushFront(&seq, 3); PushFront(&seq, 4); PrintSeqList(&seq); PopFront(&seq); PopFront(&seq); printf("\n---------------\n"); PrintSeqList(&seq); PopFront(&seq); PopFront(&seq); printf("\n---------------\n"); PopFront(&seq); printf("\n---------------\n"); PrintSeqList(&seq); } void Test3() {//在指定位置处插入一个数 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 3); PushBack(&seq, 4); PushBack(&seq, 5); PrintSeqList(&seq); Insert(&seq, 2, 2); printf("\n---------------\n"); PrintSeqList(&seq); } void Test4() {//查找指定数的位置 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PrintSeqList(&seq); printf("\n---------------\n"); printf("%d\n",Find(&seq, 2)); } void Test5() {//删除某位的值 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PrintSeqList(&seq); Erase(&seq, 3); printf("\n---------------\n"); PrintSeqList(&seq); } void Test6() {//删除某数 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PrintSeqList(&seq); Remove(&seq, 2); printf("\n---------------\n"); PrintSeqList(&seq); } void Test7() {//删除所有指定的数 SeqList seq; InitSeqList(&seq); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PushBack(&seq, 3); PushBack(&seq, 5); PushBack(&seq, 3); PrintSeqList(&seq); RemoveAll(&seq, 3); printf("\n---------------\n"); PrintSeqList(&seq); } void Test8() {//冒泡排序 SeqList seq; InitSeqList(&seq); PushBack(&seq, 8); PushBack(&seq, 7); PushBack(&seq, 3); PushBack(&seq, 4); PushBack(&seq, 6); PushBack(&seq, 5); PushBack(&seq, 1); PushBack(&seq, 2); PrintSeqList(&seq); BubbleSort(&seq); printf("\n---------------\n"); PrintSeqList(&seq); } void Test9() {//选择排序 SeqList seq; InitSeqList(&seq); PushBack(&seq, 8); PushBack(&seq, 7); PushBack(&seq, 3); PushBack(&seq, 4); PushBack(&seq, 6); PushBack(&seq, 5); PushBack(&seq, 1); PushBack(&seq, 2); PrintSeqList(&seq); SeclectSort(&seq); printf("\n---------------\n"); PrintSeqList(&seq); } void Test10() {//折半查找 SeqList seq; InitSeqList(&seq); PushBack(&seq, 0); PushBack(&seq, 1); PushBack(&seq, 2); PushBack(&seq, 3); PushBack(&seq, 4); PrintSeqList(&seq); printf("\n---------------\n"); printf("%d is position %d\n", 3, BinarySearch(&seq, 3)); } int main() { Test1(); printf("\n*********************\n"); Test2(); printf("\n*********************\n"); Test3(); printf("\n*********************\n"); Test4(); printf("\n*********************\n"); Test5(); printf("\n*********************\n"); Test6(); printf("\n*********************\n"); Test7(); printf("\n*********************\n"); Test8(); printf("\n*********************\n"); Test9(); printf("\n*********************\n"); Test10(); system("pause"); }
小知识:
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
可以采用两种方式(如上述程序中所示):
方法一,采用[]闭区间的方式。
方法二,采用[ )左闭右开的方式。