1. 程式人生 > >資料結構:陣列

資料結構:陣列

陣列和字串是兩種最基本的資料結構,陣列佔據一塊連續的記憶體並按照順序儲存資料。建立陣列時,我們需要首先指定陣列的容量大小,然後根據大小分配記憶體,因此陣列的空間效率不是很好,會有空閒的區域,導致記憶體浪費。 1.陣列與雜湊表 因為陣列中的記憶體是連續的,根據下標讀寫元素,它的效率比較高,我們可以利用陣列的時間效率高的特點去實現簡單的雜湊表:把陣列的下標設為雜湊表的鍵值,陣列中存放的值設為雜湊表的值。 2.動態陣列 為了避免浪費,設計了多種動態陣列,先為陣列開闢較小的空間。當資料的數目超出陣列的容量時,我們再重新分配一塊更大的空間。並把之前的資料複製到新記憶體中,把之前的記憶體釋放,這樣能減少記憶體浪費。但是每一次動態擴充是都會有很多的額外操作,這對時間效能不利,因此動態陣列要儘量減少改變陣列容量大小的次數。 3.陣列與指標 sizeof(指標)大小恆定為4,sizeof(陣列)是求陣列的大小。 當陣列作為函式引數進行傳遞時,陣列就會自動退化為同類型的指標。

//=========劍指offer第二版面試題50===============
//字串中第一隻出現一次的字元
//在字串中找出第一個只出現一次的字元,如輸入“abaccdeff”,則輸出‘b’
/*解題思路:在本題中我們只需要利用一個簡單的雜湊表,字元是一個長度為(0-255)*/
# include <stdio.h>
# include <string.h>


char FirstNotRepeatingChar(char * pString)
{
	if(pString == NULL)
	{
		return '\0';
	}
	const int size = 256;
	int array[size];
	for(int i=0;i<size;i++)
	{
		array[i]=0;
	}

	char *p = pString;
	while (*p!='\0')
	{
		array[*p++]++;
	}
	p=pString;
	while(*p!='\0')
	{
		if(array[*p]==1)
		{
			return *p;
		}
		p++;
	}
	return '\0';

}

//==========測試用例========
void Test(char *pString,char key)
{
	if(FirstNotRepeatingChar(pString) == key)
        printf("Test passed.\n");
    else
        printf("Test failed.\n");
}

int main()
{
    // 存在只出現一次的字元
    Test("google", 'l');

    // 不存在只出現一次的字元
    Test("aabccdbd", '\0');

    // 所有字元都只出現一次
    Test("abcdefg", 'a');

    // 輸入nullptr
    Test(nullptr, '\0');

    return 0;
}

輸出結果為: Test passed. Test passed. Test passed. Test passed. 請按任意鍵繼續. . .

//===========劍指offer第二版面試題3========
//題目一:找出陣列中重複的數字
/*解題思路:1.先把這個陣列進行排序,從排序好的陣列中從頭到尾遍歷一遍找到重複的數字時間複雜度為O(nlogn)
2.利用雜湊表來解決,需要申請一個空間為n的雜湊表,以空間換時間
3.重排這個陣列,從頭到尾掃描這個陣列,當掃描到下標為i時,首先比較這個數字m是不是等於i,如果是則繼續掃描如果不是,再拿他跟m下標下的數字
進行比較,如果它跟m下標所存放的數字相等,則找到一個重複數字,如果不相等,就把這個數與m下標的數進行互換,繼續比較,直到發現一個重複數字。
*/

# include <stdio.h>
bool duplicate(int arr[],int length,int *duplicate)
{
	if(arr == NULL || length <=0)//先排除不符合條件的情況
	{
		return false;
	}
	for(int i=0;i<length-1;i++)
	{
		if(arr[i]<0||arr[i]>length-1)
		{
			return false;
		}
	}
	for(int i=0;i<length-1;i++)
	{
		while(arr[i]!=i)
		{
			if(arr[arr[i]]==arr[i])//如果該元素與m位置元素相同,則找到了一個重複數字
			{
				*duplicate = arr[i];
				return true;
			}
			//交換該元素與m位置元素
			int temp = arr[i];
			arr[i]=arr[arr[i]];
			arr[temp]=temp;//注意在這裡犯錯為了!!第一次錯寫為arr[arr[i]],此時會陷入死迴圈
		}
	}
	return false;//直到整個陣列遍歷完,表示還沒找到,返回false
}
//==========測試用例===========
bool contains(int array[], int length, int number)
{
    for(int i = 0; i < length; ++i)
    {
        if(array[i] == number)
            return true;
    }

    return false;
}

void test(char* testName, int numbers[], int lengthNumbers, int expected[], int expectedExpected, bool validArgument)
{
    printf("%s begins: ", testName);

    int duplication;
    bool validInput = duplicate(numbers, lengthNumbers, &duplication);

    if(validArgument == validInput)
    {
        if(validArgument)
        {
            if(contains(expected, expectedExpected, duplication))
                printf("Passed.\n");
            else
                printf("FAILED.\n");
        }
        else
            printf("Passed.\n");
    }
    else
        printf("FAILED.\n");
}

// 重複的數字是陣列中最小的數字
void test1()
{
    int numbers[] = { 2, 1, 3, 1, 4 };
    int duplications[] = { 1 };
    test("Test1", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 重複的數字是陣列中最大的數字
void test2()
{
    int numbers[] = { 2, 4, 3, 1, 4 };
    int duplications[] = { 4 };
    test("Test2", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 陣列中存在多個重複的數字
void test3()
{
    int numbers[] = { 2, 4, 2, 1, 4 };
    int duplications[] = { 2, 4 };
    test("Test3", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 沒有重複的數字
void test4()
{
    int numbers[] = { 2, 1, 3, 0, 4 };
    int duplications[] = { -1 }; // not in use in the test function
    test("Test4", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}

// 沒有重複的數字
void test5()
{
    int numbers[] = { 2, 1, 3, 5, 4 };
    int duplications[] = { -1 }; // not in use in the test function
    test("Test5", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}

// 無效的輸入
void test6()
{
    int* numbers = NULL;
    int duplications[] = { -1 }; // not in use in the test function
    test("Test6", numbers, 0, duplications, sizeof(duplications) / sizeof(int), false);
}

int main()
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
	return 0;
}

輸出結果為: Test1 begins: Passed. Test2 begins: Passed. Test3 begins: Passed. Test4 begins: Passed. Test5 begins: Passed. Test6 begins: Passed. 請按任意鍵繼續. . .